0024059: Eliminate compiler warning C4701 in MSVC++ with warning level 4
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_MiddlePath.cxx
1 // File:      BRepOffsetAPI_MiddlePath.cxx
2 // Created:   06.08.12 16:53:16
3 // Author:    jgv@ROLEX
4 // Copyright: Open CASCADE 2012
5
6 #include <BRepOffsetAPI_MiddlePath.ixx>
7 #include <BRepOffsetAPI_MiddlePath.hxx>
8
9 #include <ShapeUpgrade_UnifySameDomain.hxx>
10
11 #include <gp_Lin.hxx>
12 #include <Geom_Curve.hxx>
13 #include <Geom_TrimmedCurve.hxx>
14 #include <Geom_Line.hxx>
15 #include <Geom_BezierCurve.hxx>
16 #include <Geom_BSplineCurve.hxx>
17 #include <BRep_Tool.hxx>
18 #include <gce_MakeLin.hxx>
19
20 #include <BRepLib_MakeWire.hxx>
21
22 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
23 #include <TopTools_MapIteratorOfMapOfShape.hxx>
24 #include <TopExp.hxx>
25 #include <TopTools_ListIteratorOfListOfShape.hxx>
26 #include <TopoDS.hxx>
27 #include <BRepTools.hxx>
28 #include <TopTools_SequenceOfShape.hxx>
29 #include <BRepTools_WireExplorer.hxx>
30 #include <TopoDS_Iterator.hxx>
31 #include <BRep_Builder.hxx>
32 #include <Precision.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <BRepExtrema_DistShapeShape.hxx>
35 #include <Geom2d_Curve.hxx>
36 #include <Geom2d_Line.hxx>
37 #include <GCE2d_MakeLine.hxx>
38 #include <BRepLib_MakeEdge.hxx>
39 #include <BRepLib.hxx>
40 #include <GeomAbs_CurveType.hxx>
41 #include <BRepAdaptor_Curve.hxx>
42 #include <TopTools_Array1OfShape.hxx>
43 #include <BRepLib_MakeFace.hxx>
44 #include <TColgp_Array1OfPnt.hxx>
45 #include <TColgp_HArray1OfPnt.hxx>
46 #include <TColgp_Array1OfVec.hxx>
47 #include <TColStd_HArray1OfBoolean.hxx>
48 #include <GProp_GProps.hxx>
49 #include <BRepGProp.hxx>
50 #include <Geom_Circle.hxx>
51 #include <gp_Circ.hxx>
52 #include <GC_MakeCircle.hxx>
53 #include <TColgp_SequenceOfPnt.hxx>
54 #include <GeomLib.hxx>
55 #include <GeomAPI_Interpolate.hxx>
56
57 static Standard_Boolean IsLinear(const TopoDS_Edge& anEdge,
58                                  gp_Lin& aLine)
59 {
60   Standard_Real fpar, lpar;
61   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
62   if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
63     aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
64
65   gp_Pnt Pnt1, Pnt2;
66   if (aCurve->IsKind(STANDARD_TYPE(Geom_Line)))
67   {
68     aLine = ((Handle(Geom_Line)&) aCurve)->Lin();
69     return Standard_True;
70   }
71   else if (aCurve->IsKind(STANDARD_TYPE(Geom_BezierCurve)))
72   {
73     Handle(Geom_BezierCurve) theBezier = (Handle(Geom_BezierCurve)&) aCurve;
74     if (theBezier->NbPoles() == 2)
75     {
76       Pnt1 = theBezier->Pole(1);
77       Pnt2 = theBezier->Pole(2);
78       aLine = gce_MakeLin(Pnt1, Pnt2);
79       return Standard_True;
80     }
81   }
82   else if (aCurve->IsKind(STANDARD_TYPE(Geom_BSplineCurve)))
83   {
84     Handle(Geom_BSplineCurve) theBSpline = (Handle(Geom_BSplineCurve)&) aCurve;
85     if (theBSpline->NbPoles() == 2)
86     {
87       Pnt1 = theBSpline->Pole(1);
88       Pnt2 = theBSpline->Pole(2);
89       aLine = gce_MakeLin(Pnt1, Pnt2);
90       return Standard_True;
91     }
92   }
93
94   return Standard_False;
95 }
96
97 static GeomAbs_CurveType TypeOfEdge(const TopoDS_Edge& anEdge)
98 {
99   gp_Lin aLin;
100   if (IsLinear(anEdge, aLin))
101     return GeomAbs_Line;
102
103   BRepAdaptor_Curve BAcurve(anEdge);
104   return BAcurve.GetType();
105 }
106
107 static gp_Vec TangentOfEdge(const TopoDS_Shape& aShape,
108                             const Standard_Boolean OnFirst)
109 {
110   TopoDS_Edge anEdge = TopoDS::Edge(aShape);
111   TopAbs_Orientation anOr = anEdge.Orientation();
112   
113   Standard_Real fpar, lpar;
114   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
115   Standard_Real thePar;
116   if (OnFirst)
117     thePar = (anOr == TopAbs_FORWARD)? fpar : lpar;
118   else
119     thePar = (anOr == TopAbs_FORWARD)? lpar : fpar;
120
121   gp_Pnt thePoint;
122   gp_Vec theTangent;
123   aCurve->D1(thePar, thePoint, theTangent);
124   if (anOr == TopAbs_REVERSED)
125     theTangent.Reverse();
126
127   return theTangent;
128 }
129
130
131 static Standard_Boolean IsValidEdge(const TopoDS_Edge& theEdge,
132                                     const TopoDS_Face& theFace)
133 {
134   TopoDS_Vertex V1, V2;
135   TopExp::Vertices(theEdge, V1, V2);
136
137   Standard_Real Tol = Precision::Confusion();
138   Standard_Integer i;
139   
140   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
141   for (; Explo.More(); Explo.Next())
142   {
143     const TopoDS_Shape& anEdge = Explo.Current();
144     BRepExtrema_DistShapeShape DistMini(theEdge, anEdge);
145     if (DistMini.Value() <= Tol)
146     {
147       for (i = 1; i <= DistMini.NbSolution(); i++)
148       {
149         BRepExtrema_SupportType theType = DistMini.SupportTypeShape2(i);
150         if (theType == BRepExtrema_IsOnEdge)
151           return Standard_False;
152         //theType is "IsVertex"
153         TopoDS_Shape aVertex = DistMini.SupportOnShape2(i);
154         if (!(aVertex.IsSame(V1) || aVertex.IsSame(V2)))
155           return Standard_False;
156       }
157     }
158   }
159
160   return Standard_True;
161 }
162
163 /*
164 //=======================================================================
165 //function : BRepOffsetAPI_MiddlePath
166 //purpose  : Constructor
167 //=======================================================================
168
169 BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
170                                                    const TopoDS_Wire&  StartWire)
171 {
172   myInitialShape = aShape;
173   myStartWire    = StartWire;
174   myClosedSection = myStartWire.Closed();
175 }
176
177 //=======================================================================
178 //function : BRepOffsetAPI_MiddlePath
179 //purpose  : Constructor
180 //=======================================================================
181
182 BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
183                                                    const TopoDS_Edge&  StartEdge)
184 {
185   myInitialShape = aShape;
186
187   BRepLib_MakeWire MW(StartEdge);
188   
189   //BB.Add(myStartWire, StartEdge);
190
191   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
192   TopTools_IndexedDataMapOfShapeListOfShape VEmap;
193   TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE,   TopAbs_FACE, EFmap);
194   TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
195   
196   //Standard_Boolean Start = Standard_True;
197   //if (Start)
198   //{
199   //TopExp::Vertices(CurEdge, V1, V2);
200   //  StartVertex = V1;
201   //  CurVertex   = V2;
202   //  if (VEmap(CurVertex).Extent() == 2) //end: two free edges
203   //  {
204   //    StartVertex = V2;
205   //    CurVertex   = V1;
206   //    if (VEmap(CurVertex).Extent() == 2) //end: two free edges
207   //      break;
208   //  }
209   //  Start = Standard_False;
210   //  continue;
211   //}
212
213   TopoDS_Vertex StartVertex, CurVertex, V1, V2;
214   TopExp::Vertices(StartEdge, StartVertex, CurVertex);
215   TopoDS_Edge CurEdge = StartEdge;
216   Standard_Integer i;
217   for (i = 1; i <= 2; i++)
218   {
219     for (;;)
220     {
221       const TopTools_ListOfShape& LE = VEmap.FindFromKey(CurVertex);
222       if (LE.Extent() == 2) //end: two free edges or one closed free edge
223         break;
224       TopTools_ListIteratorOfListOfShape itl(LE);
225       TopoDS_Edge anEdge;
226       for (; itl.More(); itl.Next())
227       {
228         anEdge = TopoDS::Edge(itl.Value());
229         if (anEdge.IsSame(CurEdge))
230           continue;
231         if (EFmap.FindFromKey(anEdge).Extent() == 1) //another free edge found
232           break;
233       }
234       //BB.Add(myStartWire, anEdge);
235       MW.Add(anEdge);
236       TopExp::Vertices(anEdge, V1, V2);
237       CurVertex = (V1.IsSame(CurVertex))? V2 : V1;
238       CurEdge = anEdge;
239       if (CurVertex.IsSame(StartVertex))
240         break;
241     }
242     if (CurVertex.IsSame(StartVertex))
243       break;
244     CurVertex = StartVertex;
245     CurEdge = StartEdge;
246   }
247   
248   myStartWire = MW.Wire();
249   myClosedSection = myStartWire.Closed();
250 }
251 */
252
253 //=======================================================================
254 //function : BRepOffsetAPI_MiddlePath
255 //purpose  : Constructor
256 //=======================================================================
257
258 BRepOffsetAPI_MiddlePath::BRepOffsetAPI_MiddlePath(const TopoDS_Shape& aShape,
259                                                    const TopoDS_Shape& StartShape,
260                                                    const TopoDS_Shape& EndShape)
261 {
262   ShapeUpgrade_UnifySameDomain Unifier(aShape);
263   Unifier.Build();
264   myInitialShape = Unifier.Shape();
265
266   TopoDS_Wire aStartWire, anEndWire;
267   if (StartShape.ShapeType() == TopAbs_FACE)
268   {
269     const TopoDS_Face& StartFace = TopoDS::Face(StartShape);
270     aStartWire = BRepTools::OuterWire(StartFace);
271   }
272   else
273     aStartWire = TopoDS::Wire(StartShape);
274   
275   if (EndShape.ShapeType() == TopAbs_FACE)
276   {
277     const TopoDS_Face& EndFace = TopoDS::Face(EndShape);
278     anEndWire = BRepTools::OuterWire(EndFace);
279   }
280   else
281     anEndWire = TopoDS::Wire(EndShape);
282
283   BRepLib_MakeWire MWstart;
284   //TopTools_MapOfShape MapEdges;
285   BRepTools_WireExplorer wexp(aStartWire);
286   for (; wexp.More(); wexp.Next())
287   {
288     TopoDS_Shape anEdge = wexp.Current();
289     TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
290     if (!NewEdge.IsNull())
291       MWstart.Add(TopoDS::Edge(NewEdge));
292   }
293   myStartWire = MWstart.Wire();
294
295   BRepLib_MakeWire MWend;
296   //MapEdges.Clear();
297   for (wexp.Init(anEndWire); wexp.More(); wexp.Next())
298   {
299     TopoDS_Shape anEdge = wexp.Current();
300     TopoDS_Shape NewEdge = Unifier.Generated(anEdge);
301     if (!NewEdge.IsNull())
302       MWend.Add(TopoDS::Edge(NewEdge));
303   }
304   myEndWire = MWend.Wire();
305
306   myClosedSection = myStartWire.Closed();
307   myClosedRing    = myStartWire.IsSame(myEndWire);
308 }
309
310 //=======================================================================
311 //function : Build
312 //purpose  : 
313 //=======================================================================
314
315 void BRepOffsetAPI_MiddlePath::Build()
316 {
317   TopTools_ListIteratorOfListOfShape itl;
318   
319   TopTools_SequenceOfShape StartVertices;
320   TopTools_MapOfShape EndVertices;
321   TopTools_MapOfShape EndEdges;
322   BRepOffsetAPI_SequenceOfSequenceOfShape SectionsEdges;
323   
324   BRepTools_WireExplorer wexp(myStartWire);
325   TopTools_SequenceOfShape EdgeSeq;
326   for (; wexp.More(); wexp.Next())
327   {
328     StartVertices.Append(wexp.CurrentVertex());
329     EdgeSeq.Append(wexp.Current());
330   }
331   if (!myClosedSection)
332     StartVertices.Append(wexp.CurrentVertex());
333   SectionsEdges.Append(EdgeSeq);
334   
335   for (wexp.Init(myEndWire); wexp.More(); wexp.Next())
336   {
337     EndVertices.Add(wexp.CurrentVertex());
338     EndEdges.Add(wexp.Current());
339   }
340   if (!myClosedSection)
341     EndVertices.Add(wexp.CurrentVertex());
342   
343
344   TopoDS_Iterator itw(myStartWire);
345   for (; itw.More(); itw.Next())
346     myStartWireEdges.Add(itw.Value());
347   for (itw.Initialize(myEndWire); itw.More(); itw.Next())
348     myEndWireEdges.Add(itw.Value());
349
350   TopTools_IndexedDataMapOfShapeListOfShape VEmap;
351   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
352   TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
353   TopExp::MapShapesAndAncestors(myInitialShape, TopAbs_EDGE,   TopAbs_FACE, EFmap);
354
355   TopTools_MapOfShape CurVertices;
356   
357   Standard_Integer i, j, k;
358   TopoDS_Edge anEdge;
359   TopoDS_Vertex V1, V2, NextVertex;
360   //Initialization of <myPaths>
361   for (i = 1; i <= StartVertices.Length(); i++)
362   {
363     TopTools_SequenceOfShape Edges;
364     const TopTools_ListOfShape& LE = VEmap.FindFromKey(StartVertices(i));
365     for (itl.Initialize(LE); itl.More(); itl.Next())
366     {
367       anEdge = TopoDS::Edge(itl.Value());
368       if (!myStartWireEdges.Contains(anEdge))
369       {
370         TopExp::Vertices(anEdge, V1, V2, Standard_True);
371         if (V1.IsSame(StartVertices(i)))
372           CurVertices.Add(V2);
373         else
374         {
375           anEdge.Reverse();
376           CurVertices.Add(V1);
377         }
378         Edges.Append(anEdge);
379         break;
380       }
381     }
382     myPaths.Append(Edges);
383   }
384
385   //Filling of "myPaths"
386   TopTools_ListOfShape NextVertices;
387   for (;;)
388   {
389     for (i = 1; i <= myPaths.Length(); i++)
390     {
391       const TopoDS_Shape& theShape = myPaths(i).Last();
392       TopoDS_Edge theEdge;
393       TopoDS_Vertex theVertex;
394       if (theShape.ShapeType() == TopAbs_EDGE)
395       {
396         theEdge = TopoDS::Edge(theShape);
397         theVertex = TopExp::LastVertex(theEdge, Standard_True);
398       }
399       else //last segment of path was punctual
400       {
401         theEdge = TopoDS::Edge(myPaths(i)(myPaths(i).Length()-1));
402         theVertex = TopoDS::Vertex(theShape);
403       }
404       
405       if (EndVertices.Contains(theVertex))
406         continue;
407       const TopTools_ListOfShape& LE = VEmap.FindFromKey(theVertex);
408       TopTools_MapOfShape NextEdgeCandidates;
409       for (itl.Initialize(LE); itl.More(); itl.Next())
410       {
411         anEdge = TopoDS::Edge(itl.Value());
412         if (anEdge.IsSame(theEdge))
413           continue;
414         TopExp::Vertices(anEdge, V1, V2, Standard_True);
415         if (V1.IsSame(theVertex))
416           NextVertex = V2;
417         else
418         {
419           anEdge.Reverse();
420           NextVertex = V1;
421         }
422         if (!CurVertices.Contains(NextVertex))
423           NextEdgeCandidates.Add(anEdge);
424       }
425       if (!NextEdgeCandidates.IsEmpty())
426       {
427         if (NextEdgeCandidates.Extent() > 1)
428           myPaths(i).Append(theVertex); //punctual segment of path
429         else
430         {
431           TopTools_MapIteratorOfMapOfShape mapit(NextEdgeCandidates);
432           anEdge = TopoDS::Edge(mapit.Key());
433           myPaths(i).Append(anEdge);
434           NextVertex = TopExp::LastVertex(anEdge, Standard_True);
435           NextVertices.Append(NextVertex);
436         }
437       }
438     }
439     if (NextVertices.IsEmpty())
440       break;
441     for (itl.Initialize(NextVertices); itl.More(); itl.Next())
442       CurVertices.Add(itl.Value());
443     NextVertices.Clear();
444   }
445
446   //Temporary
447   /*
448   TopoDS_Compound aCompound, aCmp1;
449   BRep_Builder BB;
450   BB.MakeCompound(aCompound);
451   BB.MakeCompound(aCmp1);
452   for (i = 1; i <= myPaths.Length(); i++)
453   {
454     TopoDS_Compound aCmp;
455     BB.MakeCompound(aCmp);
456     for (j = 1; j <= myPaths(i).Length(); j++)
457       BB.Add(aCmp, myPaths(i)(j));
458     BB.Add(aCmp1, aCmp);
459   }
460   BB.Add(aCompound, aCmp1);
461          
462   myShape = aCompound;
463
464   Done();
465   return;
466   */
467   ////////////
468   
469   //Building of set of sections
470   Standard_Integer NbE = EdgeSeq.Length();
471   Standard_Integer NbPaths = myPaths.Length();
472   Standard_Integer NbVer = myPaths.Length();
473   if (myClosedSection)
474     NbVer++;
475   i = 1;
476   for (;;)
477   {
478     for (j = 1; j <= EdgeSeq.Length(); j++)
479       EdgeSeq(j).Nullify();
480
481     Standard_Boolean ToInsertVertex = Standard_False;
482     
483     for (j = 2; j <= NbVer; j++)
484     {
485       if (!EdgeSeq(j-1).IsNull())
486         continue;
487
488       //for the end of initial shape
489       if (myPaths(j-1).Length() < i)
490       {
491         TopoDS_Edge aE1 = TopoDS::Edge(myPaths(j-1)(i-1));
492         TopoDS_Shape LastVer = TopExp::LastVertex(aE1, Standard_True);
493         myPaths(j-1).Append(LastVer);
494       }
495       if (myPaths((j<=NbPaths)? j : 1).Length() < i)
496       {
497         TopoDS_Edge aE2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i-1));
498         TopoDS_Shape LastVer = TopExp::LastVertex(aE2, Standard_True);
499         myPaths((j<=NbPaths)? j : 1).Append(LastVer);
500       }
501       //////////////////////////////
502       
503       if (ToInsertVertex)
504       {
505         if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
506         {
507           TopoDS_Edge aE1 = TopoDS::Edge(myPaths(j-1)(i));
508           TopoDS_Shape fver = TopExp::FirstVertex(aE1, Standard_True);
509           myPaths(j-1).InsertBefore(i, fver);
510         }
511         if (myPaths((j<=NbPaths)? j : 1)(i).ShapeType() == TopAbs_EDGE)
512         {
513           TopoDS_Edge aE2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i));
514           TopoDS_Shape fver = TopExp::FirstVertex(aE2, Standard_True);
515           myPaths((j<=NbPaths)? j : 1).InsertBefore(i, fver);
516         }
517         ToInsertVertex = Standard_False;
518       }
519       
520       TopoDS_Edge E1, E2;
521       if (myPaths(j-1)(i).ShapeType() == TopAbs_EDGE)
522         E1 = TopoDS::Edge(myPaths(j-1)(i));
523       if (myPaths((j<=NbPaths)? j : 1)(i).ShapeType() == TopAbs_EDGE)
524         E2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i));
525       TopoDS_Edge E12 = TopoDS::Edge(SectionsEdges(i)(j-1));
526       
527       TopoDS_Vertex PrevVertex = (E1.IsNull())? TopoDS::Vertex(myPaths(j-1)(i))
528         : TopExp::LastVertex(E1, Standard_True);
529       TopoDS_Vertex CurVertex = (E2.IsNull())? TopoDS::Vertex(myPaths((j<=NbPaths)? j : 1)(i))
530         : TopExp::LastVertex(E2, Standard_True);
531       
532       TopoDS_Edge ProperEdge;
533       const TopTools_ListOfShape& LE = VEmap.FindFromKey(PrevVertex);
534
535       for (itl.Initialize(LE); itl.More(); itl.Next())
536       {
537         anEdge = TopoDS::Edge(itl.Value());
538         TopExp::Vertices(anEdge, V1, V2);
539         if ((V1.IsSame(PrevVertex) && V2.IsSame(CurVertex) ||
540              V1.IsSame(CurVertex) && V2.IsSame(PrevVertex)) &&
541             !anEdge.IsSame(E1))
542         {
543           ProperEdge = anEdge;
544           break;
545         }
546       }
547       
548       if ((myPaths(j-1)(i)).ShapeType() == TopAbs_VERTEX &&
549           (myPaths((j<=NbPaths)? j : 1)(i)).ShapeType() == TopAbs_VERTEX)
550       {
551         EdgeSeq(j-1) = ProperEdge;
552         continue;
553       }
554
555       TopoDS_Vertex PrevPrevVer = (E1.IsNull())? PrevVertex
556         : TopExp::FirstVertex(E1, Standard_True);
557       TopoDS_Vertex PrevCurVer  = (E2.IsNull())? CurVertex
558         : TopExp::FirstVertex(E2, Standard_True);
559       if (ProperEdge.IsNull()) //no connection between these two vertices
560       {
561         //Find the face on which E1, E2 and E12 lie
562         //ToInsertVertex = Standard_False;
563         const TopoDS_Shape& EE1 = (E1.IsNull())?
564           myPaths(j-1)(i-1) : E1;
565         const TopoDS_Shape& EE2 = (E2.IsNull())?
566           myPaths((j<=NbPaths)? j : 1)(i-1) : E2;
567         const TopTools_ListOfShape& LF = EFmap.FindFromKey(EE1);
568         TopoDS_Face theFace;
569         for (itl.Initialize(LF); itl.More(); itl.Next())
570         {
571           const TopoDS_Shape& aFace = itl.Value();
572           TopExp_Explorer Explo(aFace, TopAbs_EDGE);
573           for (; Explo.More(); Explo.Next())
574           {
575             if (EE2.IsSame(Explo.Current()))
576             {
577               const TopTools_ListOfShape& LFsec = EFmap.FindFromKey(E12);
578               TopTools_ListIteratorOfListOfShape itlsec(LFsec);
579               for (; itlsec.More(); itlsec.Next())
580                 if (aFace.IsSame(itlsec.Value()))
581                 {
582                   theFace = TopoDS::Face(aFace);
583                   break;
584                 }
585               if (!theFace.IsNull())
586                 break;
587             }
588           }
589           if (!theFace.IsNull())
590             break;
591         }
592         TopTools_ListOfShape ListOneFace;
593         ListOneFace.Append(theFace);
594
595         if (E1.IsNull() || E2.IsNull())
596         {
597           if (E1.IsNull())
598             E1 = TopoDS::Edge(myPaths(j-1)(i-1));
599           if (E2.IsNull())
600             E2 = TopoDS::Edge(myPaths((j<=NbPaths)? j : 1)(i-1));
601           Standard_Real fpar1, lpar1, fpar2, lpar2;
602           Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
603           Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
604           Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
605           if (E1.Orientation() == TopAbs_FORWARD)
606           { FirstPar1 = fpar1; LastPar1 = lpar1; }
607           else
608           { FirstPar1 = lpar1; LastPar1 = fpar1; }
609           if (E2.Orientation() == TopAbs_FORWARD)
610           { FirstPar2 = fpar2; LastPar2 = lpar2; }
611           else
612           { FirstPar2 = lpar2; LastPar2 = fpar2; }
613           gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
614           gp_Pnt2d LastPnt2d  = PCurve2->Value(LastPar2);
615           Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
616           Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
617           Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
618           TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
619                                                  PrevVertex, CurVertex,
620                                                  0., len_ne);
621           BRepLib::BuildCurve3d(NewEdge);
622           EdgeSeq(j-1) = NewEdge;
623           EFmap.Add(NewEdge, ListOneFace);
624         }
625         else //E1 is edge
626         {
627           //Extract points 2d
628           Standard_Real fpar1, lpar1, fpar2, lpar2;
629           Standard_Real FirstPar1, LastPar1, FirstPar2, LastPar2;
630           Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(E1, theFace, fpar1, lpar1);
631           Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(E2, theFace, fpar2, lpar2);
632           if (E1.Orientation() == TopAbs_FORWARD)
633           { FirstPar1 = fpar1; LastPar1 = lpar1; }
634           else
635           { FirstPar1 = lpar1; LastPar1 = fpar1; }
636           if (E2.Orientation() == TopAbs_FORWARD)
637           { FirstPar2 = fpar2; LastPar2 = lpar2; }
638           else
639           { FirstPar2 = lpar2; LastPar2 = fpar2; }
640           gp_Pnt2d FirstPnt2d = PCurve1->Value(LastPar1);
641           gp_Pnt2d LastPnt2d  = PCurve2->Value(LastPar2);
642           Handle(Geom_Surface) theSurf = BRep_Tool::Surface(theFace);
643           Handle(Geom2d_Line) theLine = GCE2d_MakeLine(FirstPnt2d, LastPnt2d);
644           Standard_Real len_ne = FirstPnt2d.Distance(LastPnt2d);
645           TopoDS_Edge NewEdge = BRepLib_MakeEdge(theLine, theSurf,
646                                                  PrevVertex, CurVertex,
647                                                  0., len_ne);
648           BRepLib::BuildCurve3d(NewEdge);
649           gp_Pnt2d PrevFirstPnt2d = PCurve1->Value(FirstPar1);
650           gp_Pnt2d PrevLastPnt2d  = PCurve2->Value(FirstPar2);
651           Handle(Geom2d_Line) Line1 = GCE2d_MakeLine(PrevFirstPnt2d, LastPnt2d);
652           Handle(Geom2d_Line) Line2 = GCE2d_MakeLine(FirstPnt2d, PrevLastPnt2d);
653           Standard_Real len_ne1 = PrevFirstPnt2d.Distance(LastPnt2d);
654           TopoDS_Edge NewEdge1 = BRepLib_MakeEdge(Line1, theSurf,
655                                                   PrevPrevVer, CurVertex,
656                                                   0., len_ne1);
657           BRepLib::BuildCurve3d(NewEdge1);
658           Standard_Real len_ne2 = FirstPnt2d.Distance(PrevLastPnt2d);
659           TopoDS_Edge NewEdge2 = BRepLib_MakeEdge(Line2, theSurf,
660                                                   PrevVertex, PrevCurVer,
661                                                   0., len_ne2);
662           BRepLib::BuildCurve3d(NewEdge2);
663           Standard_Boolean good_ne  = IsValidEdge(NewEdge, theFace);
664           Standard_Boolean good_ne1 = IsValidEdge(NewEdge1, theFace);
665
666           GeomAbs_CurveType type_E1 = TypeOfEdge(E1);
667           GeomAbs_CurveType type_E2 = TypeOfEdge(E2);
668
669           Standard_Integer ChooseEdge = 0;
670           
671           if (!good_ne || type_E1 != type_E2)
672           {
673             if (type_E1 == type_E2) //!good_ne
674             {
675               if (good_ne1)
676                 ChooseEdge = 1;
677               else
678                 ChooseEdge = 2;
679             }
680             else //types are different
681             {
682               if (type_E1 == GeomAbs_Line)
683                 ChooseEdge = 1;
684               else if (type_E2 == GeomAbs_Line)
685                 ChooseEdge = 2;
686               else //to be developed later...
687               {}
688             }
689           }
690           
691           if (ChooseEdge == 0)
692           {
693             EdgeSeq(j-1) = NewEdge;
694             EFmap.Add(NewEdge, ListOneFace);
695           }
696           else if (ChooseEdge == 1)
697           {
698             EdgeSeq(j-1) = NewEdge1;
699             EFmap.Add(NewEdge1, ListOneFace);
700             for (k = 1; k < j-1; k++)
701               EdgeSeq(k).Nullify();
702             for (k = 1; k <= j-1; k++)
703             {
704               TopoDS_Edge aLastEdge = TopoDS::Edge(myPaths(k)(i));
705               TopoDS_Shape VertexAsEdge = TopExp::FirstVertex(aLastEdge, Standard_True);
706               myPaths(k).InsertBefore(i, VertexAsEdge);
707             }
708             j = 1; //start from beginning
709           }
710           else if (ChooseEdge == 2)
711           {
712             EdgeSeq(j-1) = NewEdge2;
713             EFmap.Add(NewEdge2, ListOneFace);
714             ToInsertVertex = Standard_True;
715           }
716         } //else //E1 is edge
717       } //if (ProperEdge.IsNull())
718       else //connecting edge exists
719       {
720         /*
721         if (ToInsertVertex)
722         {
723           myPaths(j-1).InsertBefore(i, PrevPrevVer);
724           myPaths((j<=NbPaths)? j : 1).InsertBefore(i, PrevCurVer);
725           EdgeSeq(j-1) = E12;
726         }
727         else
728         */
729           EdgeSeq(j-1) = ProperEdge;
730       }
731     } //for (j = 2; j <= NbVer; j++)
732     SectionsEdges.Append(EdgeSeq);
733
734     //check for exit from for(;;)
735     Standard_Integer NbEndEdges = 0;
736     for (j = 1; j <= EdgeSeq.Length(); j++)
737       if (EndEdges.Contains(EdgeSeq(j)))
738         NbEndEdges++;
739     if (NbEndEdges == NbE)
740       break;
741     
742     i++;
743   } //for (;;)
744   
745
746   //final phase: building of middle path
747   Standard_Integer NbSecFaces = SectionsEdges.Length();
748   TopTools_Array1OfShape SecFaces(1, NbSecFaces);
749   for (i = 1; i <= NbSecFaces; i++)
750   {
751     BRepLib_MakeWire MW;
752     for (j = 1; j <= NbE; j++)
753     {
754       anEdge = TopoDS::Edge(SectionsEdges(i)(j));
755       MW.Add(anEdge);
756     }
757     if (!myClosedSection)
758     {
759       TopExp::Vertices(MW.Wire(), V1, V2);
760       anEdge = BRepLib_MakeEdge(V2, V1);
761       MW.Add(anEdge);
762     }
763     TopoDS_Wire aWire = MW.Wire();
764     BRepLib_MakeFace MF(aWire, Standard_True); //Only plane
765     if (MF.IsDone())
766       SecFaces(i) = MF.Face();
767     else
768       SecFaces(i) = aWire;
769   }
770
771   TColgp_Array1OfPnt Centers(1, NbSecFaces);
772   for (i = 1; i <= NbSecFaces; i++)
773   {
774     GProp_GProps Properties;
775     if (SecFaces(i).ShapeType() == TopAbs_FACE)
776       BRepGProp::SurfaceProperties(SecFaces(i), Properties);
777     else //wire
778       BRepGProp::LinearProperties(SecFaces(i), Properties);
779       
780     Centers(i) = Properties.CentreOfMass();
781   }
782
783   TopTools_Array1OfShape MidEdges(1, NbSecFaces-1);
784   Standard_Real LinTol = 1.e-5;
785   Standard_Real AngTol = 1.e-7;
786   gp_Pnt Pnt1, Pnt2;
787   for (i = 1; i < NbSecFaces; i++)
788   {
789     GeomAbs_CurveType TypeOfMidEdge = GeomAbs_OtherCurve;
790     for (j = 1; j <= myPaths.Length(); j++)
791     {
792       const TopoDS_Shape& aShape = myPaths(j)(i);
793       if (aShape.ShapeType() == TopAbs_VERTEX)
794       {
795         TypeOfMidEdge = GeomAbs_OtherCurve;
796         break;
797       }
798       anEdge = TopoDS::Edge(aShape);
799       GeomAbs_CurveType aType = TypeOfEdge(anEdge);
800       if (j == 1)
801         TypeOfMidEdge = aType;
802       else
803       {
804         if (aType != TypeOfMidEdge)
805         {
806           TypeOfMidEdge = GeomAbs_OtherCurve;
807           break;
808         }
809       }
810     }
811     if (TypeOfMidEdge == GeomAbs_Line)
812       MidEdges(i) = BRepLib_MakeEdge(Centers(i), Centers(i+1));
813     else if (TypeOfMidEdge == GeomAbs_Circle)
814     {
815       gp_Ax1 theAxis;
816       gp_Dir theDir1, theDir2;
817       Standard_Real theAngle = 0.;
818       gp_Vec theTangent;
819       Standard_Boolean SimilarArcs = Standard_True;
820       for (j = 1; j <= myPaths.Length(); j++)
821       {
822         anEdge = TopoDS::Edge(myPaths(j)(i));
823         Standard_Real fpar, lpar;
824         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
825         if (aCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
826           aCurve = ((Handle(Geom_TrimmedCurve)&) aCurve)->BasisCurve();
827         Pnt1 = aCurve->Value(fpar);
828         Pnt2 = aCurve->Value(lpar);
829         Handle(Geom_Circle) aCircle = Handle(Geom_Circle)::DownCast(aCurve);
830         gp_Circ aCirc = aCircle->Circ();
831         if (j == 1)
832         {
833           theAxis = aCirc.Axis();
834           theDir1 = gp_Vec(aCirc.Location(), Pnt1);
835           theDir2 = gp_Vec(aCirc.Location(), Pnt2);
836           theAngle = lpar - fpar;
837           Standard_Real theParam = (anEdge.Orientation() == TopAbs_FORWARD)?
838             fpar : lpar;
839           aCurve->D1(theParam, Pnt1, theTangent);
840           if (anEdge.Orientation() == TopAbs_REVERSED)
841             theTangent.Reverse();
842         }
843         else
844         {
845           gp_Ax1 anAxis = aCirc.Axis();
846           gp_Lin aLin(anAxis);
847           if (!aLin.Contains(theAxis.Location(), LinTol) ||
848               !anAxis.IsParallel(theAxis, AngTol))
849           {
850             SimilarArcs = Standard_False;
851             break;
852           }
853           gp_Dir aDir1 = gp_Vec(aCirc.Location(), Pnt1);
854           gp_Dir aDir2 = gp_Vec(aCirc.Location(), Pnt2);
855           if (!(aDir1.IsEqual(theDir1, AngTol) && aDir2.IsEqual(theDir2, AngTol) ||
856                 aDir1.IsEqual(theDir2, AngTol) && aDir2.IsEqual(theDir1, AngTol)))
857           {
858             SimilarArcs = Standard_False;
859             break;
860           }
861         }
862       }
863       if (SimilarArcs)
864       {
865         gp_XYZ AxisLoc = theAxis.Location().XYZ();
866         gp_XYZ AxisDir = theAxis.Direction().XYZ();
867         Standard_Real Parameter = (Centers(i).XYZ() - AxisLoc) * AxisDir;
868         gp_Pnt theCenterOfCirc(AxisLoc + Parameter*AxisDir);
869         
870         gp_Vec Vec1(theCenterOfCirc, Centers(i));
871         gp_Vec Vec2(theCenterOfCirc, Centers(i+1));
872         /*
873         gp_Dir VecProd = Vec1 ^ Vec2;
874         if (theAxis.Direction() * VecProd < 0.)
875           theAxis.Reverse();
876         */
877         
878         Standard_Real anAngle = Vec1.AngleWithRef(Vec2, theAxis.Direction());
879         if (anAngle < 0.)
880           anAngle += 2.*M_PI;
881         if (Abs(anAngle - theAngle) > AngTol)
882           theAxis.Reverse();
883         gp_Ax2 theAx2(theCenterOfCirc, theAxis.Direction(), Vec1);
884         Handle(Geom_Circle) theCircle = GC_MakeCircle(theAx2, Vec1.Magnitude());
885         gp_Vec aTangent;
886         theCircle->D1( 0., Pnt1, aTangent );
887         if (aTangent * theTangent < 0.)
888         {
889           theAxis.Reverse();
890           theAx2 = gp_Ax2(theCenterOfCirc, theAxis.Direction(), Vec1);
891           theCircle = GC_MakeCircle(theAx2, Vec1.Magnitude());
892         }
893         BRepLib_MakeEdge aME (theCircle, 0., theAngle);
894         aME.Build();
895
896         MidEdges(i) = aME.IsDone() ? 
897           aME.Shape() : 
898           TopoDS_Edge();
899       }
900     }
901   }
902
903   //Build missed edges
904   for (i = 1; i < NbSecFaces; i++)
905   {
906     if (MidEdges(i).IsNull())
907     {
908       for (j = i+1; j < NbSecFaces; j++)
909       {
910         if (!MidEdges(j).IsNull())
911           break;
912       }
913       //from i to j-1 all edges are null
914       Handle(TColgp_HArray1OfPnt) thePoints = new TColgp_HArray1OfPnt(1, j-i+1);
915       TColgp_Array1OfVec theTangents(1, j-i+1);
916       Handle(TColStd_HArray1OfBoolean) theFlags = new TColStd_HArray1OfBoolean(1, j-i+1);
917       for (k = i; k <= j; k++)
918         thePoints->SetValue(k-i+1, Centers(k));
919       for (k = i; k <= j; k++)
920       {
921         TColgp_SequenceOfPnt PntSeq;
922         for (Standard_Integer indp = 1; indp <= myPaths.Length(); indp++)
923         {
924           gp_Vec aTangent;
925           if (k == i)
926           {
927             if (myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
928               continue;
929             aTangent = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
930           }
931           else if (k == j)
932           {
933             if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX)
934               continue;
935             aTangent = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
936           }
937           else
938           {
939             if (myPaths(indp)(k-1).ShapeType() == TopAbs_VERTEX ||
940                 myPaths(indp)(k).ShapeType() == TopAbs_VERTEX)
941               continue;
942             gp_Vec Tangent1 = TangentOfEdge(myPaths(indp)(k-1), Standard_False); //at end
943             gp_Vec Tangent2 = TangentOfEdge(myPaths(indp)(k), Standard_True); //at begin
944             aTangent = Tangent1 + Tangent2;
945           }
946           aTangent.Normalize();
947           gp_Pnt aPnt(aTangent.XYZ());
948           PntSeq.Append(aPnt);
949         }
950         TColgp_Array1OfPnt PntArray(1, PntSeq.Length());
951         for (Standard_Integer ip = 1; ip <= PntSeq.Length(); ip++)
952           PntArray(ip) = PntSeq(ip);
953         gp_Pnt theBary;
954         gp_Dir xdir, ydir;
955         Standard_Real xgap, ygap, zgap;
956         GeomLib::Inertia(PntArray, theBary, xdir, ydir, xgap, ygap, zgap);
957         gp_Vec theTangent(theBary.XYZ());
958         theTangents(k-i+1) = theTangent;
959       }
960       theFlags->Init(Standard_True);
961
962       GeomAPI_Interpolate Interpol(thePoints, Standard_False, LinTol);
963       Interpol.Load(theTangents, theFlags);
964       Interpol.Perform();
965       if (!Interpol.IsDone())
966       {
967         cout<<endl<<"Interpolation failed"<<endl;
968       }
969       Handle(Geom_Curve) InterCurve = Interpol.Curve();
970       MidEdges(i) = BRepLib_MakeEdge(InterCurve);
971       i = j;
972     }
973   }  
974
975   BRepLib_MakeWire MakeFinalWire;
976   for (i = 1; i < NbSecFaces; i++)
977     if (!MidEdges(i).IsNull())
978       MakeFinalWire.Add(TopoDS::Edge(MidEdges(i)));
979
980   TopoDS_Wire FinalWire = MakeFinalWire.Wire();
981   myShape = MakeFinalWire.Wire();
982   
983   //Temporary
984   /*
985   TopoDS_Compound aCompound, aCmp1, aCmp2;
986   BRep_Builder BB;
987   BB.MakeCompound(aCompound);
988   BB.MakeCompound(aCmp1);
989   BB.MakeCompound(aCmp2);
990   for (i = 1; i <= myPaths.Length(); i++)
991   {
992     TopoDS_Compound aCmp;
993     BB.MakeCompound(aCmp);
994     for (j = 1; j <= myPaths(i).Length(); j++)
995       BB.Add(aCmp, myPaths(i)(j));
996     BB.Add(aCmp1, aCmp);
997   }
998   for (i = 1; i <= SectionsEdges.Length(); i++)
999   {
1000     TopoDS_Wire aWire;
1001     BB.MakeWire(aWire);
1002     for (j = 1; j <= SectionsEdges(i).Length(); j++)
1003       BB.Add(aWire, SectionsEdges(i)(j));
1004     BB.Add(aCmp2, aWire);
1005   }
1006   BB.Add(aCompound, aCmp1);
1007   BB.Add(aCompound, aCmp2);
1008   BB.Add(aCompound, FinalWire);
1009          
1010   myShape = aCompound;
1011   */
1012   ////////////
1013
1014   Done();
1015 }