0030958: BRepOffsetAPI_ThruSections operation raises an exception while building...
[occt.git] / src / BRepOffsetAPI / BRepOffsetAPI_ThruSections.cxx
1 // Created on: 1995-07-18
2 // Created by: Joelle CHAUVET
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified:    Mon Jan 12 10:50:10 1998
18 //              gestion automatique de l'origine et de l'orientation
19 //              avec la methode ArrangeWires
20 // Modified:    Mon Jan 19 10:11:56 1998
21 //              traitement des cas particuliers cylindre, cone, plan 
22 //              (methodes DetectKPart et CreateKPart)
23 // Modified:    Mon Feb 23 09:28:46 1998
24 //              traitement des sections avec nombre d'elements different
25 //              + quelques ameliorations pour les cas particuliers
26 //              + cas de la derniere section ponctuelle
27 // Modified:    Mon Apr  6 15:47:44 1998
28 //              traitement des cas particuliers deplace dans BRepFill 
29 // Modified:    Thu Apr 30 15:24:17 1998
30 //              separation sections fermees / sections ouvertes + debug 
31 // Modified:    Fri Jul 10 11:23:35 1998
32 //              surface de CreateSmoothed par concatenation,approximation
33 //              et segmentation (PRO13924, CTS21295)
34 // Modified:    Tue Jul 21 16:48:35 1998
35 //              pb de ratio (BUC60281) 
36 // Modified:    Thu Jul 23 11:38:36 1998
37 //              sections bouclantes
38 // Modified:    Fri Aug 28 10:13:44 1998
39 //              traitement des sections ponctuelles
40 //              dans l'historique (cf. loft06 et loft09)
41 //              et dans le cas des solides
42 // Modified:    Tue Nov  3 10:06:15 1998
43 //              utilisation de BRepFill_CompatibleWires
44
45 #include <BRep_Builder.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRepBuilderAPI_FindPlane.hxx>
48 #include <BRepBuilderAPI_MakeFace.hxx>
49 #include <BRepClass3d_SolidClassifier.hxx>
50 #include <BRepFill_CompatibleWires.hxx>
51 #include <BRepFill_Generator.hxx>
52 #include <BRepLib.hxx>
53 #include <BRepOffsetAPI_ThruSections.hxx>
54 #include <BRepTools_WireExplorer.hxx>
55 #include <BSplCLib.hxx>
56 #include <Geom2d_Line.hxx>
57 #include <Geom_BezierCurve.hxx>
58 #include <Geom_BSplineCurve.hxx>
59 #include <Geom_BSplineSurface.hxx>
60 #include <Geom_Conic.hxx>
61 #include <Geom_Curve.hxx>
62 #include <Geom_Plane.hxx>
63 #include <Geom_TrimmedCurve.hxx>
64 #include <GeomAbs_Shape.hxx>
65 #include <GeomConvert.hxx>
66 #include <GeomConvert_ApproxCurve.hxx>
67 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
68 #include <GeomFill_AppSurf.hxx>
69 #include <GeomFill_Line.hxx>
70 #include <GeomFill_SectionGenerator.hxx>
71 #include <gp_Dir2d.hxx>
72 #include <gp_Pnt.hxx>
73 #include <gp_Pnt2d.hxx>
74 #include <Precision.hxx>
75 #include <Standard_DomainError.hxx>
76 #include <Standard_NullObject.hxx>
77 #include <TColgp_Array1OfPnt.hxx>
78 #include <TopAbs.hxx>
79 #include <TopExp.hxx>
80 #include <TopLoc_Location.hxx>
81 #include <TopoDS.hxx>
82 #include <TopoDS_Edge.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Iterator.hxx>
85 #include <TopoDS_Shape.hxx>
86 #include <TopoDS_Solid.hxx>
87 #include <TopoDS_Vertex.hxx>
88 #include <TopoDS_Wire.hxx>
89 #include <TopTools_Array1OfShape.hxx>
90 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
91 #include <TopTools_ListIteratorOfListOfShape.hxx>
92 #include <BRepAdaptor_Surface.hxx>
93
94 //=======================================================================
95 //function : PreciseUpar
96 //purpose  : pins the u-parameter of surface close to U-knot
97 //           to this U-knot
98 //=======================================================================
99 static Standard_Real PreciseUpar(const Standard_Real anUpar,
100   const Handle(Geom_BSplineSurface)& aSurface)
101 {
102   Standard_Real Tol = Precision::PConfusion();
103   Standard_Integer i1, i2;
104
105   aSurface->LocateU(anUpar, Tol, i1, i2);
106   Standard_Real U1 = aSurface->UKnot(i1);
107   Standard_Real U2 = aSurface->UKnot(i2);
108
109   Standard_Real NewU = anUpar;
110
111   NewU = (anUpar - U1 < U2 - anUpar)? U1 : U2;
112   return NewU;
113 }
114
115 //=======================================================================
116 //function :  PerformPlan
117 //purpose  : Construct a plane of filling if exists
118 //=======================================================================
119
120 static Standard_Boolean PerformPlan(const TopoDS_Wire& W,
121   const Standard_Real presPln,
122   TopoDS_Face& theFace)
123 {
124   Standard_Boolean isDegen = Standard_True;
125   TopoDS_Iterator iter(W);
126   for (; iter.More(); iter.Next())
127   {
128     const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
129     if (!BRep_Tool::Degenerated(anEdge))
130       isDegen = Standard_False;
131   }
132   if (isDegen)
133     return Standard_True;
134
135   Standard_Boolean Ok = Standard_False;
136   if (!W.IsNull()) {
137     BRepBuilderAPI_FindPlane Searcher( W, presPln );
138     if (Searcher.Found())
139     {
140       theFace = BRepBuilderAPI_MakeFace(Searcher.Plane(), W);
141       Ok = Standard_True;
142     }
143     else // try to find another surface
144     {
145       BRepBuilderAPI_MakeFace MF( W );
146       if (MF.IsDone())
147       {
148         theFace = MF.Face();
149         Ok = Standard_True;
150       }
151     }
152   }
153
154   return Ok;
155 }
156
157 //=============================================================================
158 //function :  IsSameOriented
159 //purpose  : Checks whether aFace is oriented to the same side as aShell or not
160 //=============================================================================
161
162 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
163   const TopoDS_Shape& aShell)
164 {
165   TopExp_Explorer Explo(aFace, TopAbs_EDGE);
166   TopoDS_Shape anEdge = Explo.Current();
167   TopAbs_Orientation Or1 = anEdge.Orientation();
168
169   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
170   TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
171
172   const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
173   TopoDS_Shape theEdge;
174   for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
175   {
176     theEdge = Explo.Current();
177     if (theEdge.IsSame(anEdge))
178       break;
179   }
180
181   TopAbs_Orientation Or2 = theEdge.Orientation();
182   if (Or1 == Or2)
183     return Standard_False;
184   return Standard_True;
185 }
186
187 //=======================================================================
188 //function : MakeSolid
189 //purpose  : 
190 //=======================================================================
191
192 static TopoDS_Solid MakeSolid(TopoDS_Shell& shell, const TopoDS_Wire& wire1,
193   const TopoDS_Wire& wire2, const Standard_Real presPln,
194   TopoDS_Face& face1, TopoDS_Face& face2)
195 {
196   if (shell.IsNull())
197     throw StdFail_NotDone("Thrusections is not build");
198   Standard_Boolean B = shell.Closed();
199   BRep_Builder BB;
200
201   if (!B)
202   {
203     // It is necessary to close the extremities 
204     B =  PerformPlan(wire1, presPln, face1);
205     if (B) {
206       B =  PerformPlan(wire2, presPln, face2);
207       if (B) {
208         if (!face1.IsNull() && !IsSameOriented( face1, shell ))
209           face1.Reverse();
210         if (!face2.IsNull() && !IsSameOriented( face2, shell ))
211           face2.Reverse();
212
213         if (!face1.IsNull())
214           BB.Add(shell, face1);
215         if (!face2.IsNull())
216           BB.Add(shell, face2);
217
218         shell.Closed(Standard_True);
219       }
220     }
221   }
222
223   TopoDS_Solid solid;
224   BB.MakeSolid(solid); 
225   BB.Add(solid, shell);
226
227   // verify the orientation the solid
228   BRepClass3d_SolidClassifier clas3d(solid);
229   clas3d.PerformInfinitePoint(Precision::Confusion());
230   if (clas3d.State() == TopAbs_IN) {
231     BB.MakeSolid(solid); 
232     TopoDS_Shape aLocalShape = shell.Reversed();
233     BB.Add(solid, TopoDS::Shell(aLocalShape));
234     //    B.Add(solid, TopoDS::Shell(newShell.Reversed()));
235   }
236
237   solid.Closed(Standard_True);
238   return solid;
239 }
240
241
242 //=======================================================================
243 //function : BRepOffsetAPI_ThruSections
244 //purpose  : 
245 //=======================================================================
246
247 BRepOffsetAPI_ThruSections::BRepOffsetAPI_ThruSections(const Standard_Boolean isSolid,
248                                                        const Standard_Boolean ruled,
249                                                        const Standard_Real pres3d):
250   myNbEdgesInSection(0),
251   myIsSolid(isSolid), myIsRuled(ruled),
252   myPres3d(pres3d),
253   myDegen1(Standard_False), myDegen2(Standard_False)
254 {
255   myWCheck = Standard_True;
256   //----------------------------
257   myParamType = Approx_ChordLength; 
258   myDegMax    = 8; 
259   myContinuity = GeomAbs_C2;
260   myCritWeights[0] = .4; 
261   myCritWeights[1] = .2; 
262   myCritWeights[2] = .4; 
263   myUseSmoothing = Standard_False;
264 }
265
266
267 //=======================================================================
268 //function : Init
269 //purpose  : 
270 //=======================================================================
271
272 void BRepOffsetAPI_ThruSections::Init(const Standard_Boolean isSolid, const Standard_Boolean ruled,
273   const Standard_Real pres3d)
274 {
275   myIsSolid = isSolid;
276   myIsRuled = ruled;
277   myPres3d = pres3d;
278   myWCheck = Standard_True;
279   //----------------------------
280   myParamType = Approx_ChordLength; 
281   myDegMax    = 6; 
282   myContinuity = GeomAbs_C2;
283   myCritWeights[0] = .4; 
284   myCritWeights[1] = .2; 
285   myCritWeights[2] = .4; 
286   myUseSmoothing = Standard_False;
287
288 }
289
290
291 //=======================================================================
292 //function : AddWire
293 //purpose  : 
294 //=======================================================================
295
296 void BRepOffsetAPI_ThruSections::AddWire(const TopoDS_Wire& wire)
297 {
298   myWires.Append(wire);
299   myInputWires.Append(wire);
300 }
301
302 //=======================================================================
303 //function : AddVertex
304 //purpose  : 
305 //=======================================================================
306
307 void BRepOffsetAPI_ThruSections::AddVertex(const TopoDS_Vertex& aVertex)
308 {
309   BRep_Builder BB;
310
311   TopoDS_Edge DegEdge;
312   BB.MakeEdge( DegEdge );
313   BB.Add( DegEdge, aVertex.Oriented(TopAbs_FORWARD) );
314   BB.Add( DegEdge, aVertex.Oriented(TopAbs_REVERSED) );
315   BB.Degenerated( DegEdge, Standard_True );
316
317   TopoDS_Wire DegWire;
318   BB.MakeWire( DegWire );
319   BB.Add( DegWire, DegEdge );
320   DegWire.Closed( Standard_True );
321
322   myWires.Append( DegWire );
323   myInputWires.Append(DegWire);
324 }
325
326 //=======================================================================
327 //function : CheckCompatibility
328 //purpose  : 
329 //=======================================================================
330
331 void BRepOffsetAPI_ThruSections::CheckCompatibility(const Standard_Boolean check)
332 {
333   myWCheck = check;
334 }
335
336
337 //=======================================================================
338 //function : Build
339 //purpose  : 
340 //=======================================================================
341
342 void BRepOffsetAPI_ThruSections::Build()
343 {
344   //Check set of section for right configuration of punctual sections
345   Standard_Integer i;
346   TopExp_Explorer explo;
347   for (i = 2; i <= myWires.Length()-1; i++)
348   {
349     Standard_Boolean wdeg = Standard_True;
350     for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
351     {
352       const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
353       wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
354     }
355     if (wdeg)
356       throw Standard_Failure("Wrong usage of punctual sections");
357   }
358   if (myWires.Length() <= 2)
359   {
360     Standard_Boolean wdeg = Standard_True;
361     for (i = 1; i <= myWires.Length(); i++)
362     {
363       for (explo.Init(myWires(i), TopAbs_EDGE); explo.More(); explo.Next())
364       {
365         const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
366         wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
367       }
368     }
369     if (wdeg)
370     {
371       throw Standard_Failure("Wrong usage of punctual sections");
372     }
373   }
374
375   myNbEdgesInSection = 0;
376   
377   if (myWCheck) {
378     // compute origin and orientation on wires to avoid twisted results
379     // and update wires to have same number of edges
380
381     // use BRepFill_CompatibleWires
382     TopTools_SequenceOfShape WorkingSections;
383     WorkingSections.Clear();
384     TopTools_DataMapOfShapeListOfShape WorkingMap;
385     WorkingMap.Clear();
386
387     // Calculate the working sections
388     BRepFill_CompatibleWires Georges(myWires);
389     Georges.Perform();
390     if (Georges.IsDone()) {
391       WorkingSections = Georges.Shape();
392       WorkingMap = Georges.Generated();
393       myDegen1 = Georges.IsDegeneratedFirstSection();
394       myDegen2 = Georges.IsDegeneratedLastSection();
395       //For each sub-edge of each section
396       //we save its splits
397       Standard_Integer IndFirstSec = 1;
398       if (Georges.IsDegeneratedFirstSection())
399         IndFirstSec = 2;
400       TopoDS_Wire aWorkingSection = TopoDS::Wire(WorkingSections(IndFirstSec));
401       myNbEdgesInSection += aWorkingSection.NbChildren();
402       for (Standard_Integer ii = 1; ii <= myWires.Length(); ii++)
403       {
404         TopoDS_Iterator itw(myWires(ii));
405         for (; itw.More(); itw.Next())
406         {
407           const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value());
408           Standard_Integer aSign = 1;
409           TopoDS_Vertex Vfirst, Vlast;
410           TopExp::Vertices(anEdge, Vfirst, Vlast);
411           TopTools_ListOfShape aNewEdges = Georges.GeneratedShapes(anEdge);
412           TColStd_ListOfInteger IList;
413           aWorkingSection = TopoDS::Wire(WorkingSections(ii));
414           Standard_Integer NbNewEdges = aNewEdges.Extent();
415           TopTools_ListIteratorOfListOfShape itl(aNewEdges);
416           for (Standard_Integer kk = 1; itl.More(); itl.Next(),kk++)
417           {
418             const TopoDS_Edge& aNewEdge = TopoDS::Edge(itl.Value());
419             Standard_Integer inde = 1;
420             BRepTools_WireExplorer wexp(aWorkingSection);
421             for (; wexp.More(); wexp.Next(), inde++)
422             {
423               const TopoDS_Shape& aWorkingEdge = wexp.Current();
424               if (aWorkingEdge.IsSame(aNewEdge))
425               {
426                 aSign = (aWorkingEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
427                 break;
428               }
429             }
430             IList.Append(inde);
431             if (kk == 1 || kk == NbNewEdges)
432             {
433               //For each sub-vertex of each section
434               //we save its index of new edge
435               TopoDS_Vertex NewVfirst, NewVlast;
436               TopExp::Vertices(aNewEdge, NewVfirst, NewVlast);
437               if (NewVfirst.IsSame(Vfirst) && !myVertexIndex.IsBound(Vfirst))
438                 myVertexIndex.Bind(Vfirst, aSign*inde);
439               if (NewVlast.IsSame(Vlast) && !myVertexIndex.IsBound(Vlast))
440                 myVertexIndex.Bind(Vlast, aSign*(-inde));
441             }
442           }
443           myEdgeNewIndices.Bind(anEdge, IList);
444         }
445       }
446     }
447     myWires = WorkingSections;
448   } //if (myWCheck)
449   else //no check
450   {
451     TopoDS_Edge anEdge;
452     for (Standard_Integer ii = 1; ii <= myWires.Length(); ii++)
453     {
454       TopExp_Explorer Explo(myWires(ii), TopAbs_EDGE);
455       Standard_Integer inde = 1;
456       for (; Explo.More(); Explo.Next(),inde++)
457       {
458         anEdge = TopoDS::Edge(Explo.Current());
459         TColStd_ListOfInteger IList;
460         IList.Append(inde);
461         myEdgeNewIndices.Bind(anEdge, IList);
462         TopoDS_Vertex V1, V2;
463         TopExp::Vertices(anEdge, V1, V2);
464         if (!myVertexIndex.IsBound(V1))
465           myVertexIndex.Bind(V1, inde);
466         if (!myVertexIndex.IsBound(V2))
467           myVertexIndex.Bind(V2, -inde);
468       }
469       inde--;
470       if (inde > myNbEdgesInSection)
471         myNbEdgesInSection = inde;
472       if (inde == 1 && BRep_Tool::Degenerated(anEdge))
473       {
474         if (ii == 1)
475           myDegen1 = Standard_True;
476         else
477           myDegen2 = Standard_True;
478       }
479     }
480   }
481
482   try {
483     // Calculate the resulting shape
484     if (myWires.Length() == 2 || myIsRuled) {
485       // create a ruled shell
486       CreateRuled();
487     }
488     else {
489       // create a smoothed shell
490       CreateSmoothed();
491     }
492   }
493   catch (Standard_Failure const&)
494   {
495     NotDone();
496     return;
497   }
498   // Encode the Regularities
499   BRepLib::EncodeRegularity(myShape);
500 }
501
502
503 //=======================================================================
504 //function : CreateRuled
505 //purpose  : 
506 //=======================================================================
507
508 void BRepOffsetAPI_ThruSections::CreateRuled()
509 {
510   Standard_Integer nbSects = myWires.Length();
511   BRepFill_Generator aGene;
512   //  for (Standard_Integer i=1; i<=nbSects; i++) {
513   Standard_Integer i;
514   for (i=1; i<=nbSects; i++) {
515     aGene.AddWire(TopoDS::Wire(myWires(i)));
516   }
517   aGene.Perform();
518   TopoDS_Shell shell = aGene.Shell();
519
520   if (myIsSolid) {
521
522     // check if the first wire is the same as the last
523     Standard_Boolean vClosed = (myWires(1).IsSame(myWires(nbSects))) ;
524
525     if (vClosed) {
526
527       TopoDS_Solid solid;      
528       BRep_Builder B;
529       B.MakeSolid(solid); 
530       B.Add(solid, shell);
531
532       // verify the orientation of the solid
533       BRepClass3d_SolidClassifier clas3d(solid);
534       clas3d.PerformInfinitePoint(Precision::Confusion());
535       if (clas3d.State() == TopAbs_IN) {
536         B.MakeSolid(solid); 
537         TopoDS_Shape aLocalShape = shell.Reversed();
538         B.Add(solid, TopoDS::Shell(aLocalShape));
539         //      B.Add(solid, TopoDS::Shell(shell.Reversed()));
540       }
541       myShape = solid;
542
543     }
544
545     else {
546
547       TopoDS_Wire wire1 = TopoDS::Wire(myWires.First());
548       TopoDS_Wire wire2 = TopoDS::Wire(myWires.Last());
549       myShape = MakeSolid(shell, wire1, wire2, myPres3d, myFirst, myLast);
550
551     }
552
553     Done();
554   }
555
556   else {
557     myShape = shell;
558     Done();
559   }
560
561   // history
562   BRepTools_WireExplorer anExp1, anExp2;
563   TopTools_IndexedDataMapOfShapeListOfShape M;
564   TopExp::MapShapesAndAncestors(shell, TopAbs_EDGE, TopAbs_FACE, M);
565   TopTools_ListIteratorOfListOfShape it;
566
567   TopTools_IndexedDataMapOfShapeListOfShape MV;
568   TopExp::MapShapesAndAncestors(shell, TopAbs_VERTEX, TopAbs_FACE, MV);
569
570   for (i=1; i<=nbSects-1; i++) {
571
572     const TopoDS_Wire& wire1 = TopoDS::Wire(myWires(i));
573     const TopoDS_Wire& wire2 = TopoDS::Wire(myWires(i+1));
574
575     anExp1.Init(wire1);
576     anExp2.Init(wire2);
577
578     Standard_Boolean tantque = anExp1.More() && anExp2.More();
579
580     while (tantque) {
581
582       const TopoDS_Shape& edge1 = anExp1.Current();
583       const TopoDS_Shape& edge2 = anExp2.Current();
584       Standard_Boolean degen1 = BRep_Tool::Degenerated(anExp1.Current());
585       Standard_Boolean degen2 = BRep_Tool::Degenerated(anExp2.Current());
586
587       TopTools_MapOfShape MapFaces;
588       if (degen2){
589         TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge2));
590         for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
591           MapFaces.Add(it.Value());
592         }
593       }
594       else {
595         for (it.Initialize(M.FindFromKey(edge2)); it.More(); it.Next()) {
596           MapFaces.Add(it.Value());
597         }
598       }
599
600       if (degen1) {
601         TopoDS_Vertex Vdegen = TopExp::FirstVertex(TopoDS::Edge(edge1));
602         for (it.Initialize(MV.FindFromKey(Vdegen)); it.More(); it.Next()) {
603           const TopoDS_Shape& Face = it.Value();
604           if (MapFaces.Contains(Face)) {
605             myEdgeFace.Bind(edge1, Face);
606             break;
607           }
608         }
609       }
610       else {
611         for (it.Initialize(M.FindFromKey(edge1)); it.More(); it.Next()) {
612           const TopoDS_Shape& Face = it.Value();
613           if (MapFaces.Contains(Face)) {
614             myEdgeFace.Bind(edge1, Face);
615             break;
616           }
617         }
618       }
619
620       if (!degen1) anExp1.Next();
621       if (!degen2) anExp2.Next();
622
623       tantque = anExp1.More() && anExp2.More();
624       if (degen1) tantque = anExp2.More();
625       if (degen2) tantque = anExp1.More();
626
627     }
628
629   }
630
631 }
632
633 //=======================================================================
634 //function : CreateSmoothed
635 //purpose  : 
636 //=======================================================================
637
638 void BRepOffsetAPI_ThruSections::CreateSmoothed()
639 {
640   // initialisation
641   Standard_Integer nbSects = myWires.Length();
642   BRepTools_WireExplorer anExp;
643
644   Standard_Boolean w1Point = Standard_True;
645   // check if the first wire is punctual
646   for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
647     w1Point = w1Point && (BRep_Tool::Degenerated(anExp.Current()));
648   }
649
650   Standard_Boolean w2Point = Standard_True;
651   // check if the last wire is punctual
652   for(anExp.Init(TopoDS::Wire(myWires(nbSects))); anExp.More(); anExp.Next()) {
653     w2Point = w2Point && (BRep_Tool::Degenerated(anExp.Current()));
654   }
655
656   Standard_Boolean vClosed = Standard_False;
657   // check if the first wire is the same as last
658   if (myWires(1).IsSame(myWires(myWires.Length()))) vClosed = Standard_True;
659
660   // find the dimension
661   Standard_Integer nbEdges=0;
662   if (!w1Point) {
663     for(anExp.Init(TopoDS::Wire(myWires(1))); anExp.More(); anExp.Next()) {
664       nbEdges++;
665     }
666   }
667   else {
668     for(anExp.Init(TopoDS::Wire(myWires(2))); anExp.More(); anExp.Next()) {
669       nbEdges++;
670     }
671   }
672
673   // recover the shapes
674   Standard_Boolean uClosed = Standard_True;
675   TopTools_Array1OfShape shapes(1, nbSects*nbEdges);
676   Standard_Integer nb=0, i, j;
677
678   for (i=1; i<=nbSects; i++) {
679     const TopoDS_Wire& wire = TopoDS::Wire(myWires(i));
680     if (!wire.Closed()) {
681       // check if the vertices are the same
682       TopoDS_Vertex V1, V2;
683       TopExp::Vertices(wire,V1,V2);
684       if ( !V1.IsSame(V2)) uClosed = Standard_False;
685     }
686     if ( (i==1 && w1Point) || (i==nbSects && w2Point) ) {
687       // if the wire is punctual
688       anExp.Init(TopoDS::Wire(wire));
689       for(j=1; j<=nbEdges; j++) {
690         nb++;
691         shapes(nb) = anExp.Current();
692       }
693     }
694     else {
695       // otherwise
696       for(anExp.Init(TopoDS::Wire(wire)); anExp.More(); anExp.Next()) {
697         nb++;
698         shapes(nb) = anExp.Current();
699       }
700     }
701   }
702
703   // create the new surface
704   TopoDS_Shell shell;
705   TopoDS_Face face;
706   TopoDS_Wire W;
707   TopoDS_Edge edge, edge1, edge2, edge3, edge4, couture;
708   TopTools_Array1OfShape vcouture(1, nbEdges);
709
710   BRep_Builder B;
711   B.MakeShell(shell);
712
713   TopoDS_Wire newW1, newW2;
714   BRep_Builder BW1, BW2;
715   BW1.MakeWire(newW1);
716   BW2.MakeWire(newW2);
717
718   TopLoc_Location loc;
719   TopoDS_Vertex v1f,v1l,v2f,v2l;
720
721   Standard_Integer nbPnts = 21;
722   TColgp_Array2OfPnt points(1, nbPnts, 1, nbSects);
723
724   // concatenate each section to get a total surface that will be segmented
725   Handle(Geom_BSplineSurface) TS;
726   TS = TotalSurf(shapes,nbSects,nbEdges,w1Point,w2Point,vClosed);
727
728   if(TS.IsNull()) {
729     return;
730   }
731
732   TopoDS_Shape firstEdge;
733   for (i=1; i<=nbEdges; i++) {  
734
735     // segmentation of TS
736     Handle(Geom_BSplineSurface) surface;
737     surface = Handle(Geom_BSplineSurface)::DownCast(TS->Copy());
738     Standard_Real Ui1,Ui2,V0,V1;
739     Ui1 = i-1;
740     Ui2 = i;
741     Ui1 = PreciseUpar(Ui1, surface);
742     Ui2 = PreciseUpar(Ui2, surface);
743     V0  = surface->VKnot(surface->FirstVKnotIndex());
744     V1  = surface->VKnot(surface->LastVKnotIndex());
745     surface->Segment(Ui1,Ui2,V0,V1);
746
747     // return vertices
748     edge =  TopoDS::Edge(shapes(i));
749     TopExp::Vertices(edge,v1f,v1l);
750     if (edge.Orientation() == TopAbs_REVERSED)
751       TopExp::Vertices(edge,v1l,v1f);
752     firstEdge = edge;
753
754     edge =  TopoDS::Edge(shapes((nbSects-1)*nbEdges+i));
755     TopExp::Vertices(edge,v2f,v2l);
756     if (edge.Orientation() == TopAbs_REVERSED)
757       TopExp::Vertices(edge,v2l,v2f);
758
759     // make the face
760     B.MakeFace(face, surface, Precision::Confusion());
761
762     // make the wire
763     B.MakeWire(W);
764
765     // make the missing edges
766     Standard_Real f1, f2, l1, l2;
767     surface->Bounds(f1,l1,f2,l2);
768
769     // --- edge 1
770     if ( w1Point ) {
771       // copy the degenerated edge
772       TopoDS_Shape aLocalShape = shapes(1).EmptyCopied();
773       edge1 =  TopoDS::Edge(aLocalShape);
774       //      edge1 =  TopoDS::Edge(shapes(1).EmptyCopied());
775       edge1.Orientation(TopAbs_FORWARD);
776     }
777     else {
778       B.MakeEdge(edge1, surface->VIso(f2), Precision::Confusion());
779     }
780     v1f.Orientation(TopAbs_FORWARD);
781     B.Add(edge1, v1f);
782     v1l.Orientation(TopAbs_REVERSED);
783     B.Add(edge1, v1l);
784     B.Range(edge1, f1, l1);
785     // processing of looping sections
786     // store edges of the 1st section
787     if (vClosed)
788       vcouture(i) = edge1;
789
790
791     // --- edge 2
792     if (vClosed)
793       edge2 = TopoDS::Edge(vcouture(i));
794     else {
795       if ( w2Point ) {
796         // copy of the degenerated edge
797         TopoDS_Shape aLocalShape = shapes(nbSects*nbEdges).EmptyCopied();
798         edge2 =  TopoDS::Edge(aLocalShape);
799         //      edge2 =  TopoDS::Edge(shapes(nbSects*nbEdges).EmptyCopied());
800         edge2.Orientation(TopAbs_FORWARD);
801       }
802       else {
803         B.MakeEdge(edge2, surface->VIso(l2), Precision::Confusion());
804       }
805       v2f.Orientation(TopAbs_FORWARD);
806       B.Add(edge2, v2f);
807       v2l.Orientation(TopAbs_REVERSED);
808       B.Add(edge2, v2l);
809       B.Range(edge2, f1, l1);
810     }
811     edge2.Reverse();
812
813
814     // --- edge 3
815     if (i==1) {
816       B.MakeEdge(edge3, surface->UIso(f1), Precision::Confusion());
817       v1f.Orientation(TopAbs_FORWARD);
818       B.Add(edge3, v1f);
819       v2f.Orientation(TopAbs_REVERSED);
820       B.Add(edge3, v2f);
821       B.Range(edge3, f2, l2);
822       if (uClosed) {
823         couture = edge3;
824       }
825     }
826     else {
827       edge3 = edge4;
828     }
829     edge3.Reverse();
830
831     // --- edge 4
832     if ( uClosed && i==nbEdges) {
833       edge4 = couture;
834     }
835     else {
836       B.MakeEdge(edge4, surface->UIso(l1), Precision::Confusion());
837       v1l.Orientation(TopAbs_FORWARD);
838       B.Add(edge4, v1l);
839       v2l.Orientation(TopAbs_REVERSED);
840       B.Add(edge4, v2l);
841       B.Range(edge4, f2, l2);
842     }
843
844     B.Add(W,edge1);
845     B.Add(W,edge4);
846     B.Add(W,edge2);
847     B.Add(W,edge3);
848
849     // set PCurve
850     if (vClosed) {
851       B.UpdateEdge(edge1,
852         new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),
853         new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
854         Precision::Confusion());
855       B.Range(edge1,face,f1,l1);
856     }
857     else {
858       B.UpdateEdge(edge1,new Geom2d_Line(gp_Pnt2d(0,f2),gp_Dir2d(1,0)),face,
859         Precision::Confusion());
860       B.Range(edge1,face,f1,l1);
861       B.UpdateEdge(edge2,new Geom2d_Line(gp_Pnt2d(0,l2),gp_Dir2d(1,0)),face,
862         Precision::Confusion());
863       B.Range(edge2,face,f1,l1);
864     }
865
866     if ( uClosed && nbEdges ==1 )  {
867       B.UpdateEdge(edge3,
868         new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),
869         new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
870         Precision::Confusion());
871       B.Range(edge3,face,f2,l2);
872
873     }
874     else {
875       B.UpdateEdge(edge3,new Geom2d_Line(gp_Pnt2d(f1,0),gp_Dir2d(0,1)),face,
876         Precision::Confusion());
877       B.Range(edge3,face,f2,l2);
878       B.UpdateEdge(edge4,new Geom2d_Line(gp_Pnt2d(l1,0),gp_Dir2d(0,1)),face,
879         Precision::Confusion());
880       B.Range(edge4,face,f2,l2);
881     }
882     B.Add(face,W);
883     B.Add(shell, face);
884
885     // complete newW1 newW2
886     TopoDS_Edge edge12 = edge1;
887     TopoDS_Edge edge22 = edge2;
888     edge12.Reverse();
889     edge22.Reverse();
890     BW1.Add(newW1, edge12);
891     BW2.Add(newW2, edge22);
892
893     // history
894     myEdgeFace.Bind(firstEdge, face);
895   }
896
897   if (uClosed && w1Point && w2Point)
898     shell.Closed(Standard_True);
899
900   if (myIsSolid) {
901
902     if (vClosed) {
903
904       TopoDS_Solid solid;
905       B.MakeSolid(solid); 
906       B.Add(solid, shell);
907
908       // verify the orientation the solid
909       BRepClass3d_SolidClassifier clas3d(solid);
910       clas3d.PerformInfinitePoint(Precision::Confusion());
911       if (clas3d.State() == TopAbs_IN) {
912         B.MakeSolid(solid); 
913         TopoDS_Shape aLocalShape = shell.Reversed();
914         B.Add(solid, TopoDS::Shell(aLocalShape));
915         //      B.Add(solid, TopoDS::Shell(shell.Reversed()));
916       }
917       myShape = solid;
918
919     }
920
921     else {
922       myShape = MakeSolid(shell, newW1, newW2, myPres3d, myFirst, myLast);
923     }
924
925     Done();
926   }
927
928   else {
929     myShape = shell;
930     Done();
931   }
932
933   TopExp_Explorer ex(myShape,TopAbs_EDGE);
934   while (ex.More()) {
935     const TopoDS_Edge& CurE = TopoDS::Edge(ex.Current());
936     B.SameRange(CurE, Standard_False);
937     B.SameParameter(CurE, Standard_False);
938     Standard_Real tol = BRep_Tool::Tolerance(CurE);
939     BRepLib::SameParameter(CurE,tol);
940     ex.Next();
941   }
942 }
943
944 //=======================================================================
945 //function : EdgeToBSpline
946 //purpose  : auxiliary -- get curve from edge and convert it to bspline
947 //           parameterized from 0 to 1
948 //=======================================================================
949
950 // NOTE: this code duplicates the same function in BRepFill_NSections.cxx
951 static Handle(Geom_BSplineCurve) EdgeToBSpline (const TopoDS_Edge& theEdge)
952 {
953   Handle(Geom_BSplineCurve) aBSCurve;
954   if (BRep_Tool::Degenerated(theEdge)) {
955     // degenerated edge : construction of a point curve
956     TColStd_Array1OfReal aKnots (1,2);
957     aKnots(1) = 0.;
958     aKnots(2) = 1.;
959
960     TColStd_Array1OfInteger aMults (1,2);
961     aMults(1) = 2;
962     aMults(2) = 2;
963
964     TColgp_Array1OfPnt aPoles(1,2);
965     TopoDS_Vertex vf, vl;
966     TopExp::Vertices(theEdge,vl,vf);
967     aPoles(1) = BRep_Tool::Pnt(vf);
968     aPoles(2) = BRep_Tool::Pnt(vl);
969
970     aBSCurve = new Geom_BSplineCurve (aPoles, aKnots, aMults, 1);
971   }
972   else
973   {
974     // get the curve of the edge
975     TopLoc_Location aLoc;
976     Standard_Real aFirst, aLast;
977     Handle(Geom_Curve) aCurve = BRep_Tool::Curve (theEdge, aLoc, aFirst, aLast);
978     if (aCurve.IsNull())
979       throw Standard_NullObject("Null 3D curve in edge");
980
981     // convert its part used by edge to bspline; note that if edge curve is bspline,
982     // conversion made via trimmed curve is still needed -- it will copy it, segment 
983     // as appropriate, and remove periodicity if it is periodic (deadly for approximator)
984     Handle(Geom_TrimmedCurve) aTrimCurve = new Geom_TrimmedCurve (aCurve, aFirst, aLast);
985
986     // special treatment of conic curve
987     if (aTrimCurve->BasisCurve()->IsKind(STANDARD_TYPE(Geom_Conic)))
988     {
989       const Handle(Geom_Curve)& aCurveTrimmed = aTrimCurve; // to avoid ambiguity
990       GeomConvert_ApproxCurve anAppr (aCurveTrimmed, Precision::Confusion(), GeomAbs_C1, 16, 14);
991       if (anAppr.HasResult())
992         aBSCurve = anAppr.Curve();
993     }
994
995     // general case
996     if (aBSCurve.IsNull())
997       aBSCurve = GeomConvert::CurveToBSplineCurve (aTrimCurve);
998
999     // apply transformation if needed
1000     if (! aLoc.IsIdentity())
1001       aBSCurve->Transform (aLoc.Transformation());
1002
1003     // reparameterize to [0,1]
1004     TColStd_Array1OfReal aKnots (1, aBSCurve->NbKnots());
1005     aBSCurve->Knots (aKnots);
1006     BSplCLib::Reparametrize (0., 1., aKnots);
1007     aBSCurve->SetKnots (aKnots);
1008   }
1009
1010   // reverse curve if edge is reversed
1011   if (theEdge.Orientation() == TopAbs_REVERSED)
1012     aBSCurve->Reverse();
1013
1014   return aBSCurve;
1015 }
1016
1017 //=======================================================================
1018 //function : TotalSurf
1019 //purpose  : 
1020 //=======================================================================
1021
1022 Handle(Geom_BSplineSurface) BRepOffsetAPI_ThruSections::
1023                           TotalSurf(const TopTools_Array1OfShape& shapes,
1024                                     const Standard_Integer NbSects,
1025                                     const Standard_Integer NbEdges,
1026                                     const Standard_Boolean w1Point,
1027                                     const Standard_Boolean w2Point,
1028                                     const Standard_Boolean vClosed) const
1029 {
1030   Standard_Integer i,j,jdeb=1,jfin=NbSects;
1031   TopoDS_Vertex vf,vl;
1032
1033   GeomFill_SectionGenerator section;
1034   Handle(Geom_BSplineSurface) surface;
1035   Handle(Geom_BSplineCurve) BS, BS1;
1036   Handle(Geom_TrimmedCurve) curvTrim;
1037
1038   if (w1Point) {
1039     jdeb++;
1040     TopoDS_Edge edge =  TopoDS::Edge(shapes(1));
1041     TopExp::Vertices(edge,vl,vf);
1042     TColgp_Array1OfPnt Extremities(1,2);
1043     Extremities(1) = BRep_Tool::Pnt(vf);
1044     Extremities(2) = BRep_Tool::Pnt(vl);
1045     TColStd_Array1OfReal Bounds(1,2);
1046     Bounds(1) = 0.;
1047     Bounds(2) = 1.;
1048     TColStd_Array1OfInteger Mult(1,2);
1049     Mult(1) = 2;
1050     Mult(2) = 2;
1051     Handle(Geom_BSplineCurve) BSPoint
1052       = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
1053     section.AddCurve(BSPoint);
1054   }
1055
1056   if (w2Point) {
1057     jfin--;
1058   }
1059
1060   for (j=jdeb; j<=jfin; j++) {
1061
1062     // case of looping sections 
1063     if (j==jfin && vClosed) {
1064       section.AddCurve(BS1);
1065     }
1066
1067     else {
1068       // read the first edge to initialise CompBS;
1069       TopoDS_Edge aPrevEdge = TopoDS::Edge (shapes((j-1)*NbEdges+1));
1070       Handle(Geom_BSplineCurve) curvBS = EdgeToBSpline (aPrevEdge);
1071
1072       // initialization
1073       GeomConvert_CompCurveToBSplineCurve CompBS(curvBS);
1074
1075       for (i=2; i<=NbEdges; i++) {  
1076         // read the edge
1077         TopoDS_Edge aNextEdge = TopoDS::Edge (shapes((j-1)*NbEdges+i));
1078         Standard_Real aTolV = Precision::Confusion();  
1079         TopExp::Vertices(aNextEdge,vf,vl);
1080         aTolV = Max(aTolV, BRep_Tool::Tolerance(vf));
1081         aTolV = Max(aTolV, BRep_Tool::Tolerance(vl));
1082         aTolV = Min(aTolV, 1.e-3);
1083         curvBS = EdgeToBSpline (aNextEdge);
1084
1085         // concatenation
1086         CompBS.Add(curvBS, aTolV, Standard_True, Standard_False, 1);
1087       }
1088
1089       // return the final section
1090       BS = CompBS.BSplineCurve();
1091       section.AddCurve(BS);
1092
1093       // case of looping sections
1094       if (j==jdeb && vClosed) {
1095         BS1 = BS;
1096       }
1097
1098     }
1099   }
1100
1101   if (w2Point) {
1102     TopoDS_Edge edge =  TopoDS::Edge(shapes(NbSects*NbEdges));
1103     TopExp::Vertices(edge,vl,vf);
1104     TColgp_Array1OfPnt Extremities(1,2);
1105     Extremities(1) = BRep_Tool::Pnt(vf);
1106     Extremities(2) = BRep_Tool::Pnt(vl);
1107     TColStd_Array1OfReal Bounds(1,2);
1108     Bounds(1) = 0.;
1109     Bounds(2) = 1.;
1110     TColStd_Array1OfInteger Mult(1,2);
1111     Mult(1) = 2;
1112     Mult(2) = 2;
1113     Handle(Geom_BSplineCurve) BSPoint
1114       = new Geom_BSplineCurve(Extremities,Bounds,Mult,1);
1115     section.AddCurve(BSPoint);
1116   }
1117
1118   section.Perform(Precision::PConfusion());
1119   Handle(GeomFill_Line) line = new GeomFill_Line(NbSects);
1120
1121   Standard_Integer nbIt = 3;
1122   if(myPres3d <= 1.e-3) nbIt = 0;
1123
1124   Standard_Integer degmin = 2, degmax = Max(myDegMax, degmin);
1125   Standard_Boolean SpApprox = Standard_True;
1126
1127   GeomFill_AppSurf anApprox(degmin, degmax, myPres3d, myPres3d, nbIt);
1128   anApprox.SetContinuity(myContinuity);
1129
1130   if(myUseSmoothing) {
1131     anApprox.SetCriteriumWeight(myCritWeights[0], myCritWeights[1], myCritWeights[2]);
1132     anApprox.PerformSmoothing(line, section);
1133   } 
1134   else {
1135     anApprox.SetParType(myParamType);
1136     anApprox.Perform(line, section, SpApprox);
1137   }
1138
1139   if(anApprox.IsDone()) {
1140     surface = 
1141       new Geom_BSplineSurface(anApprox.SurfPoles(), anApprox.SurfWeights(),
1142       anApprox.SurfUKnots(), anApprox.SurfVKnots(),
1143       anApprox.SurfUMults(), anApprox.SurfVMults(),
1144       anApprox.UDegree(), anApprox.VDegree());
1145   }
1146
1147   return surface;
1148
1149 }
1150
1151 //=======================================================================
1152 //function : FirstShape
1153 //purpose  : 
1154 //=======================================================================
1155
1156 const TopoDS_Shape& BRepOffsetAPI_ThruSections::FirstShape() const
1157 {
1158   return myFirst;
1159 }
1160
1161 //=======================================================================
1162 //function : LastShape
1163 //purpose  : 
1164 //=======================================================================
1165
1166 const TopoDS_Shape& BRepOffsetAPI_ThruSections::LastShape() const
1167 {
1168   return myLast;
1169 }
1170
1171 //=======================================================================
1172 //function : Generated
1173 //purpose  : 
1174 //=======================================================================
1175 const TopTools_ListOfShape& 
1176 BRepOffsetAPI_ThruSections::Generated(const TopoDS_Shape& S) 
1177 {
1178   myGenerated.Clear();
1179
1180   TopTools_SequenceOfShape AllFaces;
1181   TopExp_Explorer Explo(myShape, TopAbs_FACE);
1182   for (; Explo.More(); Explo.Next())
1183     AllFaces.Append(Explo.Current());
1184
1185   if (S.ShapeType() == TopAbs_EDGE)
1186   {
1187     if (!myEdgeNewIndices.IsBound(S))
1188       return myGenerated;
1189
1190     const TColStd_ListOfInteger& Indices = myEdgeNewIndices(S);
1191     //Append the faces corresponding to <Indices>
1192     //These faces "grow" from the first section
1193     TColStd_ListIteratorOfListOfInteger itl(Indices);
1194     for (; itl.More(); itl.Next())
1195     {
1196       Standard_Integer IndOfFace = itl.Value();
1197       myGenerated.Append(AllFaces(IndOfFace));
1198     }
1199
1200     if (myIsRuled)
1201       //Append the next faces corresponding to <Indices>
1202       for (Standard_Integer i = 2; i < myWires.Length(); i++)
1203         for (itl.Initialize(Indices); itl.More(); itl.Next())
1204         {
1205           Standard_Integer IndOfFace = itl.Value();
1206           IndOfFace += (i-1)*myNbEdgesInSection;
1207           myGenerated.Append(AllFaces(IndOfFace));
1208         }
1209   }
1210   else if (S.ShapeType() == TopAbs_VERTEX)
1211   {
1212     if (!myVertexIndex.IsBound(S))
1213       return myGenerated;
1214
1215     TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1216     
1217     Standard_Boolean IsDegen [2] = {Standard_False, Standard_False};
1218     if (myDegen1 || myDegen2)
1219     {
1220       TopoDS_Shape EndSections [2];
1221       EndSections[0] = myWires(1);
1222       EndSections[1] = myWires(myWires.Length());
1223       for (Standard_Integer i = 0; i < 2; i++)
1224       {
1225         if (i == 0 && !myDegen1)
1226           continue;
1227         if (i == 1 && !myDegen2)
1228           continue;
1229         
1230         Explo.Init(EndSections[i], TopAbs_VERTEX);
1231         const TopoDS_Shape& aVertex = Explo.Current();
1232         if (S.IsSame(aVertex))
1233         {
1234           IsDegen[i] = Standard_True;
1235           break;
1236         }
1237       }
1238     }
1239     // Only one of <IsDegen> can be True:
1240     // in case of one vertex for start and end degenerated sections
1241     // IsDegen[0] is True;
1242     if (IsDegen[0] || IsDegen[1])
1243     {
1244       //For start or end degenerated section
1245       //we return the whole bunch of longitudinal edges
1246       TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1247       TopTools_IndexedMapOfShape Emap;
1248       const TopTools_ListOfShape& Elist = VEmap.FindFromKey(S);
1249       TopTools_ListIteratorOfListOfShape itl(Elist);
1250       for (; itl.More(); itl.Next())
1251       {
1252         const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value());
1253         if (!BRep_Tool::Degenerated(anEdge))
1254         {
1255           TopoDS_Vertex VV [2];
1256           TopExp::Vertices(anEdge, VV[0], VV[1]);
1257           //Comprehensive check for possible case of
1258           //one vertex for start and end degenerated sections:
1259           //we must take only outgoing or only ingoing edges
1260           if ((IsDegen[0] && S.IsSame(VV[0])) ||
1261               (IsDegen[1] && S.IsSame(VV[1])))
1262             Emap.Add(anEdge);
1263         }
1264       }
1265       for (Standard_Integer j = 1; j <= Emap.Extent(); j++)
1266       {
1267         TopoDS_Edge anEdge = TopoDS::Edge(Emap(j));
1268         myGenerated.Append(anEdge);
1269         if (myIsRuled)
1270         {
1271           Standard_Integer i,k;
1272           for (i = 2,k = myWires.Length()-1; i < myWires.Length(); i++,k--)
1273           {
1274             Standard_Integer IndOfSec = (IsDegen[0])? i : k;
1275             TopoDS_Vertex aVertex = (IsDegen[0])?
1276               TopExp::LastVertex(anEdge) : TopExp::FirstVertex(anEdge);
1277             const TopTools_ListOfShape& EElist = VEmap.FindFromKey(aVertex);
1278             TopTools_IndexedMapOfShape EmapOfSection;
1279             TopExp::MapShapes(myWires(IndOfSec), TopAbs_EDGE, EmapOfSection);
1280             TopoDS_Edge NextEdge;
1281             for (itl.Initialize(EElist); itl.More(); itl.Next())
1282             {
1283               NextEdge = TopoDS::Edge(itl.Value());
1284               if (!NextEdge.IsSame(anEdge) &&
1285                   !EmapOfSection.Contains(NextEdge))
1286                 break;
1287             }
1288             myGenerated.Append(NextEdge);
1289             anEdge = NextEdge;
1290           }
1291         }
1292       }
1293       return myGenerated;
1294     } //end of if (IsDegen[0] || IsDegen[1])
1295     
1296     Standard_Integer Eindex = myVertexIndex(S);
1297     Standard_Integer Vindex = (Eindex > 0)? 0 : 1;
1298     Eindex = Abs(Eindex);
1299     const TopoDS_Wire& FirstSection = TopoDS::Wire(myWires(1));
1300     TopoDS_Edge FirstEdge;
1301     TopoDS_Vertex FirstVertexOfFirstEdge;
1302     BRepTools_WireExplorer wexp(FirstSection);
1303     for (Standard_Integer inde = 1; wexp.More(); wexp.Next(),inde++)
1304     {
1305       FirstEdge = wexp.Current();
1306       FirstVertexOfFirstEdge = wexp.CurrentVertex();
1307       if (inde == Eindex)
1308         break;
1309     }
1310
1311     //Find the first longitudinal edge
1312     TopoDS_Face FirstFace = TopoDS::Face(AllFaces(Eindex));
1313     FirstFace.Orientation(TopAbs_FORWARD);
1314     Explo.Init(FirstFace, TopAbs_EDGE);
1315     TopoDS_Edge anEdge;
1316     BRepAdaptor_Surface BAsurf(FirstFace, Standard_False);
1317     TopoDS_Vertex FirstVertex;
1318     TopExp::MapShapesAndAncestors(FirstFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1319     if (myDegen1 && BAsurf.GetType() == GeomAbs_Plane)
1320     {
1321       //There are only 3 edges in the face in this case:
1322       //we take 1-st or 3-rd edge
1323       if (Vindex == 0)
1324       {
1325         Explo.Next();
1326         Explo.Next();
1327       }
1328       anEdge = TopoDS::Edge(Explo.Current());
1329     }
1330     else
1331     {
1332       TopoDS_Shape FirstEdgeInFace;
1333       FirstEdgeInFace = Explo.Current();
1334       TopoDS_Vertex VV [2];
1335       TopExp::Vertices(FirstEdge, VV[0], VV[1]);
1336       if (Vindex == 0)
1337       {
1338         if (VV[0].IsSame(FirstVertexOfFirstEdge))
1339           FirstVertex = VV[0];
1340         else
1341           FirstVertex = VV[1];
1342       }
1343       else //Vindex == 1
1344       {
1345         if (VV[0].IsSame(FirstVertexOfFirstEdge))
1346           FirstVertex = VV[1];
1347         else
1348           FirstVertex = VV[0];
1349       }
1350       const TopTools_ListOfShape& Elist = VEmap.FindFromKey(FirstVertex);
1351       TopTools_ListIteratorOfListOfShape itl(Elist);
1352       TopAbs_Orientation anEdgeOr = (Vindex == 0)? TopAbs_REVERSED : TopAbs_FORWARD;
1353       for (; itl.More(); itl.Next())
1354       {
1355         anEdge = TopoDS::Edge(itl.Value());
1356         if (!anEdge.IsSame(FirstEdgeInFace) &&
1357             !BRep_Tool::Degenerated(anEdge) &&
1358             anEdge.Orientation() == anEdgeOr)
1359           break;
1360       }
1361     }
1362     myGenerated.Append(anEdge);
1363     if (myIsRuled)
1364       //Find the chain of longitudinal edges from first to last
1365       for (Standard_Integer i = 2; i < myWires.Length(); i++)
1366       {
1367         FirstVertex = TopExp::LastVertex(anEdge);
1368         const TopTools_ListOfShape& Elist1 = VEmap.FindFromKey(FirstVertex);
1369         FirstEdge = (anEdge.IsSame(Elist1.First()))?
1370           TopoDS::Edge(Elist1.Last()) : TopoDS::Edge(Elist1.First());
1371         Eindex += myNbEdgesInSection;
1372         FirstFace = TopoDS::Face(AllFaces(Eindex));
1373         FirstFace.Orientation(TopAbs_FORWARD);
1374         VEmap.Clear();
1375         TopExp::MapShapesAndAncestors(FirstFace, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1376         const TopTools_ListOfShape& Elist2 = VEmap.FindFromKey(FirstVertex);
1377         anEdge = (FirstEdge.IsSame(Elist2.First()))?
1378           TopoDS::Edge(Elist2.Last()) : TopoDS::Edge(Elist2.First());
1379         myGenerated.Append(anEdge);
1380       }
1381   }
1382
1383   return myGenerated;
1384 }
1385
1386 //=======================================================================
1387 //function : GeneratedFace
1388 //purpose  : 
1389 //=======================================================================
1390
1391 TopoDS_Shape BRepOffsetAPI_ThruSections::GeneratedFace(const TopoDS_Shape& edge) const
1392 {
1393   TopoDS_Shape bid;
1394   if (myEdgeFace.IsBound(edge)) {
1395     return myEdgeFace(edge);
1396   }
1397   else {
1398     return bid;
1399   }
1400 }
1401
1402
1403 //=======================================================================
1404 //function : CriteriumWeight
1405 //purpose  : returns the Weights associated  to the criterium used in
1406 //           the  optimization.
1407 //=======================================================================
1408 //
1409 void BRepOffsetAPI_ThruSections::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const 
1410 {
1411   W1 = myCritWeights[0];
1412   W2 = myCritWeights[1];
1413   W3 = myCritWeights[2];
1414 }
1415 //=======================================================================
1416 //function : SetCriteriumWeight
1417 //purpose  : 
1418 //=======================================================================
1419
1420 void BRepOffsetAPI_ThruSections::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
1421 {
1422   if (W1 < 0 || W2 < 0 || W3 < 0 ) throw Standard_DomainError();
1423   myCritWeights[0] = W1;
1424   myCritWeights[1] = W2;
1425   myCritWeights[2] = W3;
1426 }
1427 //=======================================================================
1428 //function : SetContinuity
1429 //purpose  : 
1430 //=======================================================================
1431
1432 void BRepOffsetAPI_ThruSections::SetContinuity (const GeomAbs_Shape TheCont)
1433 {
1434   myContinuity = TheCont;
1435 }
1436
1437 //=======================================================================
1438 //function : Continuity
1439 //purpose  : 
1440 //=======================================================================
1441
1442 GeomAbs_Shape BRepOffsetAPI_ThruSections::Continuity () const
1443 {
1444   return myContinuity;
1445 }
1446
1447 //=======================================================================
1448 //function : SetParType
1449 //purpose  : 
1450 //=======================================================================
1451
1452 void BRepOffsetAPI_ThruSections::SetParType (const Approx_ParametrizationType ParType)
1453 {
1454   myParamType = ParType;
1455 }
1456
1457 //=======================================================================
1458 //function : ParType
1459 //purpose  : 
1460 //=======================================================================
1461
1462 Approx_ParametrizationType BRepOffsetAPI_ThruSections::ParType () const
1463 {
1464   return myParamType;
1465 }
1466
1467 //=======================================================================
1468 //function : SetMaxDegree
1469 //purpose  : 
1470 //=======================================================================
1471
1472 void BRepOffsetAPI_ThruSections:: SetMaxDegree(const Standard_Integer MaxDeg)
1473 {
1474   myDegMax = MaxDeg;
1475 }
1476
1477 //=======================================================================
1478 //function : MaxDegree
1479 //purpose  : 
1480 //=======================================================================
1481
1482 Standard_Integer  BRepOffsetAPI_ThruSections::MaxDegree () const
1483 {
1484   return myDegMax;
1485 }
1486
1487 //=======================================================================
1488 //function : SetSmoothing
1489 //purpose  : 
1490 //=======================================================================
1491
1492 void BRepOffsetAPI_ThruSections::SetSmoothing(const Standard_Boolean UseVar)
1493 {
1494   myUseSmoothing = UseVar;
1495 }
1496
1497 //=======================================================================
1498 //function : UseSmoothing
1499 //purpose  : 
1500 //=======================================================================
1501
1502 Standard_Boolean BRepOffsetAPI_ThruSections::UseSmoothing () const
1503 {
1504   return myUseSmoothing;
1505 }
1506
1507
1508
1509
1510