Salome HOME
92c766c3e423b2c92495afa949a2699899d42c56
[modules/hydro.git] / src / HYDROData / HYDROData_PolylineOperator.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include <HYDROData_PolylineOperator.h>
20 #include <HYDROData_Document.h>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRepBuilderAPI_MakeEdge2d.hxx>
24 #include <BRepBuilderAPI_MakeWire.hxx>
25 #include <Extrema_ExtCC.hxx>
26 #include <Extrema_ExtPC.hxx>
27 #include <NCollection_Vector.hxx>
28 #include <Precision.hxx>
29 #include <ShapeAnalysis_TransferParametersProj.hxx>
30 #include <ShapeBuild_Edge.hxx>
31 #include <TopoDS.hxx>
32 #include <TopoDS_Edge.hxx>
33 #include <TopoDS_Wire.hxx>
34 #include <TopExp.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
37 #include <QString>
38
39 template<class T> void append( std::vector<T>& theList, const std::vector<T>& theList2 )
40 {
41   int aSize = theList.size();
42   int aNewSize = aSize + theList2.size();
43
44   if( aSize==aNewSize )
45     return;
46
47   theList.resize( aNewSize );
48   for( int i=aSize, j=0; i<aNewSize; i++, j++ )
49     theList[i] = theList2[j];
50 }
51
52 static Standard_Boolean WireToCurve(
53   const TopoDS_Wire& theWire,
54   NCollection_Vector<TopoDS_Edge>& theEdges,
55   Standard_Boolean& theIsClosed)
56 {
57   TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
58   TopExp::MapShapesAndAncestors(theWire,
59     TopAbs_VERTEX, TopAbs_EDGE, aVertexToEdges);
60   const Standard_Integer aVCount = aVertexToEdges.Extent();
61   if (aVCount == 0)
62   {
63     return Standard_False;
64   }
65
66   {
67     Standard_Integer aEndCount = 0;
68     for (Standard_Integer aVN = 1; aVN <= aVCount; ++aVN)
69     {
70       const Standard_Integer aEdgeCount =
71         aVertexToEdges.FindFromIndex(aVN).Extent();
72       if (aEdgeCount == 1)
73       {
74         ++aEndCount;
75       }
76       if (aEdgeCount > 2)
77       {
78         return Standard_False;
79       }
80     }
81     theIsClosed = (aEndCount == 0);
82     if (!theIsClosed && aEndCount != 2)
83     {
84       return Standard_False;
85     }
86   }
87
88   Standard_Integer aVN = 1;
89   if (!theIsClosed)
90   {
91     while (aVN <= aVCount &&
92       aVertexToEdges.FindFromIndex(aVN).Extent() == 2)
93     {
94       ++aVN;
95     }
96   }
97
98   TopTools_ListOfShape* aEdges = &aVertexToEdges.ChangeFromIndex(aVN);
99   while (!aEdges->IsEmpty())
100   {
101     const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
102     aEdges->RemoveFirst();
103     theEdges.Append(aEdge);
104     Standard_Integer aVN2 =
105       aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
106     if (aVN2 == aVN)
107     {
108       aVN2 = aVertexToEdges.FindIndex(TopExp::LastVertex(aEdge));
109     }
110     aVN = aVN2;
111
112     aEdges = &aVertexToEdges.ChangeFromIndex(aVN2);
113     if (aEdges->First().IsEqual(aEdge))
114     {
115       aEdges->RemoveFirst();
116     }
117     else
118     {
119       const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
120       aEdges->Clear();
121       aEdges->Append(aEdge);
122     }
123   }
124   return (!theIsClosed && theEdges.Size() == aVCount - 1) ||
125     (theIsClosed && theEdges.Size() == aVCount);
126 }
127
128 static void CurveToWire(
129   const NCollection_Vector<TopoDS_Edge>& theEdges, TopoDS_Wire& theWire)
130 {
131   BRep_Builder aBulder;
132   aBulder.MakeWire(theWire);
133   NCollection_Vector<TopoDS_Edge>::Iterator aEIt(theEdges);
134   for (; aEIt.More(); aEIt.Next())
135   {
136     aBulder.Add(theWire, aEIt.Value());
137   }
138 }
139
140 static void CurveToWire(
141   const NCollection_Vector<TopoDS_Edge>& theEdges1,
142   const NCollection_Vector<TopoDS_Edge>& theEdges2,
143   TopoDS_Wire& theWire)
144 {
145   BRep_Builder aBulder;
146   aBulder.MakeWire(theWire);
147   const NCollection_Vector<TopoDS_Edge>* aEdges[] = {&theEdges1, &theEdges2};
148   for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
149   {
150     NCollection_Vector<TopoDS_Edge>::Iterator aEIt(*aEdges[aEI]);
151     for (; aEIt.More(); aEIt.Next())
152     {
153       aBulder.Add(theWire, aEIt.Value());
154     }
155   }
156 }
157
158 static Standard_Real ProjectPointToCurve(
159   const gp_Pnt& thePoint,
160   const Adaptor3d_Curve& theCurve,
161   Standard_Real& theParameter)
162 {
163   Extrema_ExtPC aAlgo(thePoint, theCurve);
164   Standard_Integer aMinEN = -2;
165   Standard_Real aMinSqDist = DBL_MAX;
166   if (aAlgo.IsDone())
167   {
168     const Standard_Integer aECount = aAlgo.NbExt();
169     for (Standard_Integer aEN = 1; aEN <= aECount; ++aEN)
170     {
171       const gp_Pnt& aP = aAlgo.Point(aEN).Value();
172       const Standard_Real aSqDist = thePoint.SquareDistance(aP);
173       if (aMinSqDist > aSqDist)
174       {
175         aMinSqDist = aSqDist;
176         aMinEN = aEN;
177       }
178     }
179   }
180
181   const Standard_Real aParams[] =
182     {theCurve.FirstParameter(), theCurve.LastParameter()};
183   const gp_Pnt aEnds[] =
184     {theCurve.Value(aParams[0]), theCurve.Value(aParams[1])};
185   const Standard_Real aSqDists[] =
186     {thePoint.SquareDistance(aEnds[0]), thePoint.SquareDistance(aEnds[1])};
187   for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
188   {
189     if (aMinSqDist > aSqDists[aEI])
190     {
191       aMinSqDist = aSqDists[aEI];
192       aMinEN = -aEI;
193     }
194   }
195
196   if (aMinEN <= 0)
197   {
198     theParameter = aParams[-aMinEN];
199     return aMinSqDist;
200   }
201
202   const Extrema_POnCurv& aPOnC = aAlgo.Point(aMinEN);
203   const gp_Pnt& aPoint = aPOnC.Value();
204   theParameter = aPOnC.Parameter();
205   for (Standard_Integer aEI = 0; aEI < 2; ++aEI)
206   {
207     if (Abs(theParameter - aParams[aEI]) < Precision::PConfusion() ||
208       aPoint.SquareDistance(aEnds[aEI]) < Precision::SquareConfusion())
209     {
210       theParameter = aParams[aEI];
211     }
212   }
213   return aMinSqDist;
214 }
215
216 static Standard_Real ProjectPointToEdge(
217   const gp_Pnt& thePoint,
218   const TopoDS_Edge& theEdge,
219   Standard_Real& theParameter)
220 {
221   return ProjectPointToCurve(thePoint, BRepAdaptor_Curve(theEdge), theParameter);
222 }
223
224 static void SplitCurveByPoint(
225   const NCollection_Vector<TopoDS_Edge>& theEdges,
226   const Standard_Integer theEdgeIndex,
227   const Standard_Real theParameter,
228   NCollection_Vector<TopoDS_Edge>& theEdges1,
229   NCollection_Vector<TopoDS_Edge>& theEdges2)
230 {
231   for (Standard_Integer aEI = 0; aEI < theEdgeIndex; ++aEI)
232   {
233     theEdges1.Append(theEdges(aEI));
234   }
235
236   const TopoDS_Edge& aEdge = theEdges(theEdgeIndex);
237   BRepAdaptor_Curve aCurve(aEdge);
238   Standard_Integer aParamI = -1;
239   const Standard_Real aEdgeEndParams[] =
240     {aCurve.FirstParameter(), aCurve.LastParameter()};
241   if (Abs(theParameter - aEdgeEndParams[0]) < Precision::PConfusion())
242   {
243     aParamI = 0;
244   }
245   else if (Abs(theParameter - aEdgeEndParams[1]) < Precision::PConfusion())
246   {
247     aParamI = 1;
248   }
249
250   const TopAbs_Orientation aOrient = aEdge.Orientation();
251   if (aOrient == TopAbs_REVERSED)
252   {
253     aParamI ^= 1;
254   }
255
256   const Standard_Integer aECount = theEdges.Size();
257   if (aParamI == 0)
258   {
259     NCollection_Vector<TopoDS_Edge>* aEdges = (theEdgeIndex != 0) ? &theEdges1 : &theEdges2;
260     for (Standard_Integer aEI = theEdgeIndex; aEI < aECount; ++aEI)
261     {
262       aEdges->Append(theEdges(aEI));
263     }
264   }
265   else if (aParamI == 1)
266   {
267     theEdges1.Append(aEdge);
268     for (Standard_Integer aEI = theEdgeIndex; aEI < aECount; ++aEI)
269     {
270       theEdges2.Append(theEdges(aEI));
271     }
272   }
273   else
274   {
275     TopoDS_Edge aFE = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD));
276     ShapeAnalysis_TransferParametersProj aSATPP(aFE, TopoDS_Face());
277     aSATPP.SetMaxTolerance(Precision::Confusion());
278     TopoDS_Vertex aSplitV1, aSplitV2;
279     BRep_Builder().MakeVertex(
280       aSplitV1, aCurve.Value(theParameter), Precision::Confusion());
281     BRep_Builder().MakeVertex(
282       aSplitV2, aCurve.Value(theParameter), Precision::Confusion());
283
284     TopoDS_Edge aEParts[] = {
285       ShapeBuild_Edge().CopyReplaceVertices(aFE, TopoDS_Vertex(),
286         TopoDS::Vertex(aSplitV1.Oriented(TopAbs_REVERSED))),
287       ShapeBuild_Edge().CopyReplaceVertices(aFE, aSplitV2, TopoDS_Vertex())};
288     ShapeBuild_Edge().CopyPCurves(aEParts[0], aFE);
289     ShapeBuild_Edge().CopyPCurves(aEParts[1], aFE);
290     BRep_Builder().SameRange(aEParts[0], Standard_False);
291     BRep_Builder().SameRange(aEParts[1], Standard_False);
292     BRep_Builder().SameParameter(aEParts[0], Standard_False);
293     BRep_Builder().SameParameter(aEParts[1], Standard_False);
294     aSATPP.TransferRange(aEParts[0],
295       aEdgeEndParams[0], theParameter, Standard_False);
296     aSATPP.TransferRange(aEParts[1],
297       theParameter, aEdgeEndParams[1], Standard_False);
298     aEParts[0].Orientation(aOrient);
299     aEParts[1].Orientation(aOrient);
300
301     const Standard_Integer aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
302     theEdges1.Append(aEParts[aFirstPI]);
303     theEdges2.Append(aEParts[1 - aFirstPI]);
304
305     for (Standard_Integer aEI = theEdgeIndex + 1; aEI < aECount; ++aEI)
306     {
307       theEdges2.Append(theEdges(aEI));
308     }
309   }
310 }
311
312 static void SplitCurveByPoints(
313   const NCollection_Vector<TopoDS_Edge>& theCurve,
314   const NCollection_Vector<NCollection_Sequence<Standard_Real> >& theParameters,
315   NCollection_Vector<NCollection_Vector<TopoDS_Edge> >& theSplittedCurves)
316 {
317   NCollection_Vector<TopoDS_Edge> aCurves[3];
318   aCurves[0] = theCurve;
319   Standard_Integer aCI = 0, aEI = 0;
320   NCollection_Vector<TopoDS_Edge>::Iterator aEIt(theCurve);
321   for (NCollection_Vector<NCollection_Sequence<Standard_Real> >::Iterator
322     aPLIt(theParameters); aPLIt.More(); ++aEI, aEIt.Next(), aPLIt.Next())
323   {
324     const Standard_Boolean isForward =
325       (aEIt.Value().Orientation() != TopAbs_REVERSED);
326     for (NCollection_Sequence<Standard_Real>::Iterator
327       aPIt(aPLIt.Value(), isForward); aPIt.More(); aPIt.Next())
328     {
329       const Standard_Integer aCI1 = (aCI + 1) % 3, aCI2 = (aCI + 2) % 3;
330       SplitCurveByPoint(aCurves[aCI], aEI,
331         aPIt.Value(), aCurves[aCI1], aCurves[aCI2]);
332       if (!aCurves[aCI2].IsEmpty())
333       {
334         theSplittedCurves.Append(aCurves[aCI1]);
335         aCurves[aCI].Clear();
336         aCI = aCI2;
337         aEI = 0;
338       }
339       aCurves[aCI1].Clear();
340     }
341   }
342   theSplittedCurves.Append(aCurves[aCI]);
343 }
344
345 static Standard_Integer AppendIntersectionPoint(
346   const Adaptor3d_Curve& theCurve,
347   const Standard_Real theParameter,
348   NCollection_Sequence<Standard_Real>& theParameters)
349 {
350   // Check the coincidence.
351   NCollection_Sequence<Standard_Real> aEndParams;
352   aEndParams.Append(theCurve.FirstParameter());
353   aEndParams.Append(theCurve.LastParameter());
354   NCollection_Sequence<Standard_Real>* aParams[] =
355     {&theParameters, &aEndParams};
356   const gp_Pnt aPoint = theCurve.Value(theParameter);
357   for (Standard_Integer aLI = 0; aLI < 2; ++aLI)
358   {
359     NCollection_Sequence<Standard_Real>::Iterator aPIt(*aParams[aLI]);
360     for (Standard_Integer aPI = 0; aPIt.More(); aPIt.Next(), ++aPI)
361     {
362       const Standard_Real aParam = aPIt.Value();
363       if (Abs(theParameter - aParam) < Precision::PConfusion() ||
364         aPoint.SquareDistance(theCurve.Value(aParam)) <=
365           Precision::SquareConfusion())
366       {
367         Standard_Integer aIntCount = 0;
368         if (aLI != 0)
369         {
370           if (aPI == 0)
371           {
372             theParameters.Prepend(aEndParams.First());
373           }
374           else
375           {
376             theParameters.Append(aEndParams.Last());
377           }
378           ++aIntCount;
379         }
380         return aIntCount;
381       }
382     }
383   }
384
385   // Calculate the position to insert.
386   NCollection_Sequence<Standard_Real>::Iterator aPIt(theParameters);
387   if (aPIt.More() && aPIt.Value() < theParameter)
388   {
389     NCollection_Sequence<Standard_Real>::Iterator aPIt2 = aPIt;
390     aPIt2.Next();
391     for (; aPIt2.More() && aPIt2.Value() < theParameter;
392       aPIt.Next(), aPIt2.Next());
393     theParameters.InsertAfter(aPIt, theParameter);
394   }
395   else
396   {
397     theParameters.Prepend(theParameter);
398   }
399   return 1;
400 }
401
402 static Standard_Integer IntersectEdge(
403   const TopoDS_Edge& theEdge1,
404   const TopoDS_Edge& theEdge2,
405   NCollection_Sequence<Standard_Real>& theParameters)
406 {
407   // Process the ends.
408   Standard_Integer aIntCount = 0;
409   BRepAdaptor_Curve aCurve1 = BRepAdaptor_Curve(theEdge1);
410   BRepAdaptor_Curve aCurve2 = BRepAdaptor_Curve(theEdge2);
411   const gp_Pnt aEndPs[] = {aCurve2.Value(aCurve2.FirstParameter()),
412     aCurve2.Value(aCurve2.LastParameter())};
413   for (Standard_Integer aPI = 0; aPI < 2; ++aPI)
414   {
415     Standard_Real aParameter;
416     if (ProjectPointToCurve(aEndPs[aPI], aCurve1, aParameter) <=
417       Precision::SquareConfusion())
418     {
419       AppendIntersectionPoint(aCurve1, aParameter, theParameters);
420     }
421   }
422
423   // Process the internal extrema.
424   Extrema_ExtCC aAlgo(aCurve1, aCurve2);
425   if (aAlgo.IsDone())
426   {
427     const Standard_Integer aECount = aAlgo.NbExt();
428     for (Standard_Integer aEN = 1; aEN <= aECount; ++aEN)
429     {
430       Extrema_POnCurv aP1, aP2;
431       aAlgo.Points(aEN, aP1, aP2);
432       if (aP1.Value().SquareDistance(aP2.Value()) <=
433         Precision::SquareConfusion())
434       {
435         AppendIntersectionPoint(aCurve1, aP1.Parameter(), theParameters);
436       }
437     }
438   }
439   return aIntCount;
440 }
441
442 static Standard_Integer IntersectCurve(
443   const NCollection_Vector<TopoDS_Edge>& theEdges,
444   const TopoDS_Wire& theWire,
445   NCollection_Vector<NCollection_Sequence<Standard_Real> >& theParameters)
446 {
447   Standard_Integer aIntCount = 0;
448   const Standard_Integer aECount1 = theEdges.Size();
449   for (Standard_Integer aEI1 = 0; aEI1 < aECount1; ++aEI1)
450   {
451     const TopoDS_Edge& aEdge1 = theEdges(aEI1);
452     TopExp_Explorer aEIt2(theWire, TopAbs_EDGE);
453     for (; aEIt2.More(); aEIt2.Next())
454     {
455       aIntCount += IntersectEdge(aEdge1,
456         TopoDS::Edge(aEIt2.Current()), theParameters(aEI1));
457     }
458   }
459   return aIntCount;
460 }
461
462 bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc,
463                                         const Handle( HYDROData_PolylineXY )& thePolyline,
464                                         const gp_Pnt2d& thePoint,
465                                         double theTolerance ) const
466 {
467   std::vector<gp_Pnt2d> aPointsList( 1 );
468   aPointsList[0] = thePoint;
469   std::vector<TopoDS_Wire> aCurves = GetWires( thePolyline );
470   bool isOK = true;
471   for( int i=0, n=aCurves.size(); i<n; i++ )
472   {
473     std::vector<TopoDS_Shape> aCurvesList = Split( aCurves[i], thePoint, theTolerance );
474     bool isLocalOK = CreatePolylines( theDoc, thePolyline->GetName(), aCurvesList, true );
475     isOK = isOK && isLocalOK;
476   }
477   return isOK;
478 }
479
480 bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc,
481               const Handle( HYDROData_PolylineXY )& thePolyline,
482               const Handle( HYDROData_PolylineXY )& theTool,
483               double theTolerance ) const
484 {
485   HYDROData_SequenceOfObjects aSeq;
486   aSeq.Append( theTool );
487   return split( theDoc, thePolyline, aSeq, theTolerance, -1 );
488 }
489
490 bool HYDROData_PolylineOperator::Split( const Handle( HYDROData_Document )& theDoc,
491                                         const HYDROData_SequenceOfObjects& thePolylines,
492                                         double theTolerance )
493 {
494   int f = thePolylines.Lower(), l = thePolylines.Upper();
495   for( int i=f; i<=l; i++ )
496   {
497     Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) );
498     if( !split( theDoc, aPolyline, thePolylines, theTolerance, i ) )
499       return false;
500   }
501   return true;
502 }
503
504 bool HYDROData_PolylineOperator::Merge( const Handle( HYDROData_Document )& theDoc,
505                                         const QString& theName,
506                                         const HYDROData_SequenceOfObjects& thePolylines,
507                                         bool isConnectByNewSegment,
508                                         double theTolerance )
509 {
510   TopoDS_Shape aMergedPolyline;
511
512   int f = thePolylines.Lower(), l = thePolylines.Upper();
513   for( int i=f; i<=l; i++ )
514   {
515     Handle( HYDROData_PolylineXY ) aPolyline = Handle( HYDROData_PolylineXY )::DownCast( thePolylines.Value( i ) );
516     std::vector<TopoDS_Wire> aCurves = GetWires( aPolyline );
517     for( int j=0, m=aCurves.size(); j<m; j++ )
518       if( !Merge( aMergedPolyline, aCurves[j], isConnectByNewSegment, theTolerance ) )
519         return false;
520   }
521
522   std::vector<TopoDS_Shape> aShapes( 1 );
523   aShapes[0] = aMergedPolyline;
524   CreatePolylines( theDoc, theName, aShapes, false );
525
526   return true;
527 }
528
529 bool HYDROData_PolylineOperator::Merge( TopoDS_Shape& theShape, const TopoDS_Wire& theWire, 
530                                         bool isConnectByNewSegment, double theTolerance )
531 {
532   //TODO
533   return true;
534 }
535
536 bool HYDROData_PolylineOperator::split( const Handle( HYDROData_Document )& theDoc,
537                                         const Handle( HYDROData_PolylineXY )& thePolyline,
538                                         const HYDROData_SequenceOfObjects& theTools,
539                                         double theTolerance,
540                                         int theIgnoreIndex ) const
541 {
542   std::vector<TopoDS_Wire> aCurves = GetWires( thePolyline );
543   std::vector<TopoDS_Wire> aToolCurves;
544   for( int i=theTools.Lower(), n=theTools.Upper(); i<=n; i++ )
545     if( i!=theIgnoreIndex )
546     {
547       Handle( HYDROData_PolylineXY ) aToolPolyline = 
548         Handle( HYDROData_PolylineXY )::DownCast( theTools.Value( i ) );
549       append( aToolCurves, GetWires( aToolPolyline ) );
550     }
551
552   const int aPSCount = aCurves.size();
553   const int aTSCount = aToolCurves.size();
554   std::vector<TopoDS_Shape> aResult;
555   for (int aPSI = 0; aPSI < aPSCount; ++aPSI)
556   {
557     NCollection_Vector<TopoDS_Edge> aCurve;
558     Standard_Boolean aIsClosed;
559     if (!WireToCurve(aCurves[aPSI], aCurve, aIsClosed))
560     {
561       continue;
562     }
563
564     NCollection_Vector<NCollection_Sequence<Standard_Real> > aParams;
565     aParams.SetValue(aPSCount - 1, NCollection_Sequence<Standard_Real>());
566     for (int aTSI = 0; aTSI < aTSCount; ++aTSI)
567     {
568       IntersectCurve(aCurve, aToolCurves[aTSI], aParams);
569     }
570
571     NCollection_Vector<NCollection_Vector<TopoDS_Edge> > aSplittedCurves;
572     SplitCurveByPoints(aCurve, aParams, aSplittedCurves);
573
574     Standard_Boolean aIsClosed2 = aIsClosed;
575     if (aIsClosed2)
576     {
577       const NCollection_Sequence<Standard_Real>& aPs = aParams.First();
578       if (!aPs.IsEmpty())
579       {
580         const TopoDS_Edge& aEdge = aCurve.First();
581         const Standard_Boolean isForward =
582           (aEdge.Orientation() != TopAbs_REVERSED);
583         const Standard_Real aParam = isForward ? aPs.First() : aPs.Last();
584         BRepAdaptor_Curve aCurve(aEdge);
585         const Standard_Real aEndParam = isForward ?
586           aCurve.FirstParameter() : aCurve.LastParameter();
587         aIsClosed2 = (Abs(aParam - aEndParam) > Precision::PConfusion());
588       }
589
590       if (aIsClosed2)
591       {
592         const NCollection_Sequence<Standard_Real>& aPs = aParams.Last();
593         if (!aPs.IsEmpty())
594         {
595           const TopoDS_Edge& aEdge = aCurve.Last();
596           const Standard_Boolean isForward =
597             (aEdge.Orientation() != TopAbs_REVERSED);
598           const Standard_Real aParam = isForward ? aPs.Last() : aPs.First();
599           BRepAdaptor_Curve aCurve(aEdge);
600           const Standard_Real aEndParam = isForward ?
601             aCurve.LastParameter() : aCurve.FirstParameter();
602           aIsClosed2 = (Abs(aParam - aEndParam) >= Precision::PConfusion());
603         }
604       }
605     }
606
607     Standard_Integer aFSCI = 0, aLSCI = aSplittedCurves.Size() - 1;
608     if (aIsClosed2 && aFSCI < aLSCI)
609     {
610       TopoDS_Wire aWire;
611       CurveToWire(aSplittedCurves(aLSCI), aSplittedCurves(aFSCI), aWire);
612       aResult.push_back(aWire);
613       ++aFSCI;
614       --aLSCI;
615     }
616
617     for (Standard_Integer aSCI = aFSCI; aSCI <= aLSCI; ++aSCI)
618     {
619       TopoDS_Wire aWire;
620       CurveToWire(aSplittedCurves(aSCI), aWire);
621       aResult.push_back(aWire);
622     }
623   }
624
625   CreatePolylines(theDoc, thePolyline->GetName(), aResult, true);
626   return true;
627 }
628
629 std::vector<TopoDS_Wire> HYDROData_PolylineOperator::GetWires( const Handle( HYDROData_PolylineXY )& thePolyline )
630 {
631   std::vector<TopoDS_Wire> aResult;
632
633   TopoDS_Shape aShape = thePolyline->GetShape();
634
635   if( aShape.ShapeType()==TopAbs_WIRE )
636   {
637     aResult.push_back( TopoDS::Wire( aShape ) );
638   }
639   else
640   {
641     TopExp_Explorer anExp( aShape, TopAbs_WIRE );
642     for( ; anExp.More(); anExp.Next() )
643     {
644       aResult.push_back( TopoDS::Wire( anExp.Current() ) );
645     }
646   }
647   return aResult;
648 }
649
650 std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire,
651                                                              const gp_Pnt2d& thePoint,
652                                                              double theTolerance )
653 {
654   std::vector<TopoDS_Shape> aResult;
655   NCollection_Vector<TopoDS_Edge> aEdges;
656   Standard_Boolean isClosed;
657   if (!WireToCurve(theWire, aEdges, isClosed))
658   {
659     aResult.push_back(theWire);
660     return aResult;
661   }
662
663   const gp_Pnt aP(thePoint.X(), thePoint.Y(), 0);
664   Standard_Real aMinSqDist = DBL_MAX;
665   int aSEI = -1;
666   Standard_Real aSParam;
667   for (int aECount = aEdges.Size(), aEI = 0; aEI < aECount; ++aEI)
668   {
669     Standard_Real aParam;
670     const Standard_Real aSqDist =
671       ProjectPointToEdge(aP, aEdges(aEI), aParam);
672     if (aMinSqDist > aSqDist)
673     {
674       aMinSqDist = aSqDist;
675       aSEI = aEI;
676       aSParam = aParam;
677     }
678   }
679
680   NCollection_Vector<TopoDS_Edge> aEdges1, aEdges2;
681   SplitCurveByPoint(aEdges, aSEI, aSParam, aEdges1, aEdges2);
682   TopoDS_Wire aWire;
683   if (!isClosed)
684   {
685     CurveToWire(aEdges1, aWire);
686     if (!aEdges2.IsEmpty())
687     {
688       aResult.push_back(aWire);
689       CurveToWire(aEdges2, aWire);
690     }
691   }
692   else
693   {
694     if (!aEdges2.IsEmpty())
695     {
696       CurveToWire(aEdges2, aEdges1, aWire);
697     }
698     else
699     {
700       CurveToWire(aEdges1, aWire);
701     }
702   }
703   aResult.push_back(aWire);
704   return aResult;
705 }
706
707 std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const TopoDS_Wire& theWire,
708                                                              const TopoDS_Wire& theTool,
709                                                              double theTolerance )
710 {
711   std::vector<TopoDS_Shape> aResult;
712   NCollection_Vector<TopoDS_Edge> aWEdges, aTEdges;
713   Standard_Boolean aIsWClosed, aIsTClosed;
714   if (!WireToCurve(theWire, aWEdges, aIsWClosed) ||
715     !WireToCurve(theTool, aTEdges, aIsTClosed))
716   {
717     return aResult;
718   }
719
720
721   //TODO
722   return aResult;
723 }
724
725 std::vector<TopoDS_Shape> HYDROData_PolylineOperator::Split( const std::vector<TopoDS_Wire>& theWires,
726                                                              double theTolerance )
727 {
728   std::vector<TopoDS_Shape> aResult;
729   //TODO
730   return aResult;
731 }
732
733 bool HYDROData_PolylineOperator::CreatePolylines( const Handle( HYDROData_Document )& theDoc,
734                                                   const QString& theNamePrefix,
735                                                   const std::vector<TopoDS_Shape>& theShapes,
736                                                   bool isUseIndices )
737 {
738   if( theDoc.IsNull() )
739     return false;
740
741   int n = theShapes.size();
742   int anIndex = 1;
743   for( int i=0; i<n; i++ )
744   {
745     Handle( HYDROData_PolylineXY ) aPolyline = 
746       Handle( HYDROData_PolylineXY )::DownCast( theDoc->CreateObject( KIND_POLYLINEXY ) );
747     if( aPolyline.IsNull() )
748       return false;
749
750     aPolyline->SetShape( theShapes[i] );
751
752     if( isUseIndices )
753     {
754       QString aNewName = theNamePrefix + "_" + QString::number( anIndex );
755       if( theDoc->FindObjectByName( aNewName ).IsNull() )  // the object with such a name is not found
756         aPolyline->SetName( aNewName );
757       anIndex++;
758     }
759     else
760     {
761       aPolyline->SetName( theNamePrefix );
762     }
763   }
764   return true;
765 }