208af33901949c00da58e403ddd736af8fa74be1
[occt.git] / src / BRepFill / BRepFill_PipeShell.cxx
1 // Created on: 1998-07-22
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #include <stdio.h>
23
24 #include <BRepFill_PipeShell.ixx>
25
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <TopExp.hxx>
29 #include <TopTools_SequenceOfShape.hxx>
30 #include <TopoDS.hxx>
31 #include <TopoDS_Shell.hxx>
32 #include <TopoDS_Solid.hxx>
33 #include <TopoDS_Iterator.hxx>
34 #include <TopLoc_Location.hxx>
35
36 #include <BRepLib_MakeEdge.hxx>
37 #include <BRepLib_MakeFace.hxx>
38 #include <BRepAdaptor_HCompCurve.hxx>
39 #include <BRepClass3d_SolidClassifier.hxx>
40
41 #include <BRepFill.hxx>
42 #include <BRepFill_Sweep.hxx>
43 #include <BRepFill_SectionPlacement.hxx>
44 #include <BRepFill_Edge3DLaw.hxx>
45 #include <BRepFill_ACRLaw.hxx>
46 #include <BRepFill_EdgeOnSurfLaw.hxx>
47 #include <BRepFill_ShapeLaw.hxx>
48 #include <BRepFill_CompatibleWires.hxx>
49 #include <BRepFill_NSections.hxx>
50 #include <TColStd_HArray1OfReal.hxx>
51
52 #include <GeomFill_TrihedronLaw.hxx>
53 #include <GeomFill_CorrectedFrenet.hxx>
54 #include <GeomFill_Frenet.hxx>
55 #include <GeomFill_Fixed.hxx>
56 #include <GeomFill_ConstantBiNormal.hxx>
57 #include <GeomFill_SectionLaw.hxx>
58 #include <GeomFill_CurveAndTrihedron.hxx>
59 #include <GeomFill_GuideTrihedronAC.hxx>
60 #include <GeomFill_GuideTrihedronPlan.hxx>
61 #include <GeomFill_LocationGuide.hxx>
62
63 //Specification Guide
64 #include <GeomAdaptor_HCurve.hxx>
65
66 #include <gp_Trsf.hxx>
67 #include <gp_Dir.hxx>
68 #include <gp_Vec.hxx>
69 #include <Precision.hxx>
70
71 #include <Standard_NotImplemented.hxx>
72 #include <Standard_ConstructionError.hxx>
73 #include <StdFail_NotDone.hxx>
74
75 #include <BRepBuilderAPI_Copy.hxx>
76
77 #ifdef DRAW
78 #include <Draw.hxx>
79 #include <DrawTrSurf.hxx>
80 #include <DBRep.hxx>
81 static Standard_Boolean Affich = 0;
82 #endif
83
84 #include <TopTools_ListIteratorOfListOfShape.hxx>
85 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
86 #include <TopoDS_Compound.hxx>
87
88 static Standard_Boolean UpdateMap(const TopoDS_Shape&                 theKey,
89                                   const TopoDS_Shape&                 theValue,
90                                   TopTools_DataMapOfShapeListOfShape& theMap);
91
92 static Standard_Boolean BuildBoundaries(const BRepFill_Sweep&               theSweep,
93                                         const Handle(BRepFill_SectionLaw)&  theSection,
94                                         TopoDS_Shape&                       theBottom,
95                                         TopoDS_Shape&                       theTop);
96
97 //=======================================================================
98 //function :  ComputeSection
99 //purpose  : Construct an intermediary section
100 //=======================================================================
101
102 static Standard_Boolean ComputeSection(const TopoDS_Wire& W1,
103                                        const TopoDS_Wire& W2,
104                                        const Standard_Real p1,
105                                        const Standard_Real p2,
106                                        TopoDS_Wire& Wres)
107 {
108   TColStd_SequenceOfReal SR;
109   TopTools_SequenceOfShape SSh;
110   SR.Clear();
111   SR.Append(0.);
112   SR.Append(1.);
113   SSh.Clear();
114   SSh.Append(W1);
115   SSh.Append(W2);
116   BRepFill_CompatibleWires CW(SSh);
117   CW.SetPercent(0.1);
118   CW.Perform();
119   if (!CW.IsDone()) StdFail_NotDone::Raise("Uncompatible wires");
120   GeomFill_SequenceOfTrsf EmptyTrsfs;
121   Handle(BRepFill_NSections) SL = new (BRepFill_NSections) (CW.Shape(),EmptyTrsfs,SR,0.,1.);
122   Standard_Real US = p1/(p1+p2);
123   SL->D0(US, Wres);
124   return Standard_True;
125 }
126
127                                       
128
129 //=======================================================================
130 //function : PerformTransition
131 //purpose  : Modify a law of location depending on Transition
132 //=======================================================================
133
134 static void PerformTransition(const BRepFill_TransitionStyle Mode,
135                               Handle(BRepFill_LocationLaw)& Loc,
136                               const Standard_Real angmin)
137 {
138  if (!Loc.IsNull()) {
139    Loc->DeleteTransform();
140    if (Mode == BRepFill_Modified) Loc->TransformInG0Law();
141    else  Loc->TransformInCompatibleLaw(angmin);
142  } 
143 }
144 //=======================================================================
145 //function :  PerformPlan
146 //purpose  : Construct a plane of filling if exists
147 //=======================================================================
148
149 static Standard_Boolean PerformPlan(TopoDS_Shape& S)
150 {
151   Standard_Boolean isDegen = Standard_True;
152   TopExp_Explorer explo(S, TopAbs_EDGE);
153   for (; explo.More(); explo.Next())
154     {
155       const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
156       if (!BRep_Tool::Degenerated(anEdge))
157         isDegen = Standard_False;
158     }
159   if (isDegen)
160     {
161       S.Nullify();
162       return Standard_True;
163     }
164
165   TopoDS_Wire W = TopoDS::Wire(S);
166   Standard_Boolean Ok = Standard_False;
167   if (!W.IsNull()) {
168     BRepLib_MakeFace mkplan(W, Standard_True);
169     if (mkplan.IsDone()) {
170       S = mkplan.Face();
171       Ok = Standard_True;
172     }
173   }
174  return Ok;
175 }
176
177 //=============================================================================
178 //function :  IsSameOriented
179 //purpose  : Checks whether aFace is oriented to the same side as aShell or not
180 //=============================================================================
181
182 static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace,
183                                        const TopoDS_Shape& aShell)
184 {
185   TopExp_Explorer Explo(aFace, TopAbs_EDGE);
186   TopoDS_Shape anEdge = Explo.Current();
187   TopAbs_Orientation Or1 = anEdge.Orientation();
188
189   TopTools_IndexedDataMapOfShapeListOfShape EFmap;
190   TopExp::MapShapesAndAncestors( aShell, TopAbs_EDGE, TopAbs_FACE, EFmap );
191
192   const TopoDS_Shape& AdjacentFace = EFmap.FindFromKey(anEdge).First();
193   TopoDS_Shape theEdge;
194   for (Explo.Init(AdjacentFace, TopAbs_EDGE); Explo.More(); Explo.Next())
195     {
196       theEdge = Explo.Current();
197       if (theEdge.IsSame(anEdge))
198         break;
199     }
200
201   TopAbs_Orientation Or2 = theEdge.Orientation();
202   if (Or1 == Or2)
203     return Standard_False;
204   return Standard_True;
205 }
206 //=======================================================================
207 //function : BRepFill_PipeShell
208 //purpose  : 
209 //=======================================================================
210 BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine)
211                       :  mySpine(Spine), 
212                          myTrihedron(GeomFill_IsCorrectedFrenet),
213                          myTransition(BRepFill_Modified),
214                          myStatus(GeomFill_PipeOk)
215 {
216   myLocation.Nullify();
217   mySection.Nullify();
218   myLaw.Nullify();
219   SetTolerance();
220
221   // Attention to closed non-declared wire !
222   if (!mySpine.Closed()) {
223     TopoDS_Vertex Vf, Vl;
224     TopExp::Vertices(mySpine, Vf, Vl);
225     if (Vf.IsSame(Vl)) mySpine.Closed(Standard_True);
226   }  
227 }
228
229 //=======================================================================
230 //function : Set
231 //purpose  : Define a law of Frenet (Correct)
232 //=======================================================================
233  void BRepFill_PipeShell::Set(const Standard_Boolean IsFrenet) 
234 {
235   Handle(GeomFill_TrihedronLaw) TLaw;
236   if (IsFrenet) {
237     myTrihedron = GeomFill_IsFrenet;
238     TLaw = new (GeomFill_Frenet) ();
239   }
240   else {
241     myTrihedron = GeomFill_IsFrenet;
242     TLaw = new (GeomFill_CorrectedFrenet) ();
243   }
244   Handle(GeomFill_CurveAndTrihedron) Loc = 
245     new (GeomFill_CurveAndTrihedron) (TLaw);
246   myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
247   mySection.Nullify(); //It is required to relocalize sections.
248 }
249
250 //=======================================================================
251 //function : Set
252 //purpose  : Define a law Constant
253 //=======================================================================
254  void BRepFill_PipeShell::Set(const gp_Ax2& Axe) 
255 {
256   myTrihedron = GeomFill_IsFixed;
257   gp_Vec V1, V2;
258   V1.SetXYZ(Axe.Direction().XYZ());
259   V2.SetXYZ(Axe.XDirection().XYZ());
260   Handle(GeomFill_Fixed) TLaw = new (GeomFill_Fixed) (V1, V2);
261   Handle(GeomFill_CurveAndTrihedron) Loc = 
262     new (GeomFill_CurveAndTrihedron) (TLaw);
263   myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc); 
264   mySection.Nullify(); //It is required to relocalize sections.
265 }
266
267 //=======================================================================
268 //function : Set
269 //purpose  : Construct a law of location of binormal fixed type
270 //=======================================================================
271  void BRepFill_PipeShell::Set(const gp_Dir& BiNormal) 
272 {
273   myTrihedron = GeomFill_IsConstantNormal;
274
275   Handle(GeomFill_ConstantBiNormal) TLaw = 
276     new (GeomFill_ConstantBiNormal) (BiNormal);
277   Handle(GeomFill_CurveAndTrihedron) Loc = 
278     new (GeomFill_CurveAndTrihedron) (TLaw);
279   myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc); 
280   mySection.Nullify(); //Il faut relocaliser les sections.
281 }
282
283 //=======================================================================
284 //function : Set
285 //purpose  : Construct a law of location of Darboux type
286 //=======================================================================
287  Standard_Boolean BRepFill_PipeShell::Set(const TopoDS_Shape& SpineSupport) 
288 {
289  Standard_Boolean B;
290
291   // A special law of location is required
292  Handle(BRepFill_EdgeOnSurfLaw) loc = 
293    new (BRepFill_EdgeOnSurfLaw) (mySpine, SpineSupport);
294  B = loc->HasResult();
295  if (B) {
296    myLocation = loc; 
297    myTrihedron = GeomFill_IsDarboux;
298    mySection.Nullify(); //It is required to relocalize the sections.
299  }
300  return B;
301 }
302
303 //=======================================================================
304 //function : Set
305 //purpose  : Defines a lawv with help of a guided contour
306 //=======================================================================
307  void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine,
308                               const Standard_Boolean CurvilinearEquivalence,
309                               const Standard_Boolean KeepContact) 
310 {  
311   // Reorganization of the guide (pb of orientation and origin)
312   TopoDS_Wire TheGuide;
313   TheGuide =  AuxiliarySpine;
314   Standard_Boolean SpClose = mySpine.Closed(), 
315                    GuideClose = AuxiliarySpine.Closed();
316
317   if (!SpClose && !GuideClose) {
318     // Case open reorientation of the guide
319     TopoDS_Wire sp = mySpine;
320     TopTools_SequenceOfShape Seq;
321     Seq.Append(sp);
322     Seq.Append(TheGuide);
323     BRepFill_CompatibleWires CW(Seq);
324     CW.SetPercent(0.1);
325     CW.Perform();
326     if (!CW.IsDone()) StdFail_NotDone::Raise("Uncompatible wires");
327     TheGuide = TopoDS::Wire(CW.Shape().Value(2));
328   }
329   else if (GuideClose) {
330     // Case guide closed : Determination of the origin 
331     // & reorientation of the guide
332     gp_Vec Dir;
333     gp_Pnt SpOr;
334     if (!SpClose) {
335       TopoDS_Vertex Vf, Vl;
336       gp_Pnt P;
337       TopExp::Vertices(mySpine, Vf, Vl);
338       SpOr = BRep_Tool::Pnt(Vf);
339       P = BRep_Tool::Pnt(Vl);
340       gp_Vec V(P, SpOr);
341       SpOr.BaryCenter(0.5, P, 0.5);
342       Dir = V;
343     }
344     else {
345       BRepAdaptor_CompCurve BC(mySpine);
346       BC.D1(0,SpOr,Dir); 
347     } 
348     BRepFill::SearchOrigin(TheGuide, SpOr, Dir, 100*myTol3d);
349   }
350
351 #ifdef DRAW
352   if (Affich)
353     DBRep::Set("theguide", TheGuide);
354 #endif
355   // transform the guide in a single curve (periodic if posssible)
356   Handle(BRepAdaptor_HCompCurve) Guide  = 
357     new (BRepAdaptor_HCompCurve) (TheGuide);
358   Guide->ChangeCurve().SetPeriodic(Standard_True);
359
360   if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa
361     if (KeepContact) 
362       myTrihedron = GeomFill_IsGuideACWithContact; // with rotation 
363     else
364       myTrihedron = GeomFill_IsGuideAC; // without rotation 
365       
366     Handle(GeomFill_GuideTrihedronAC) TLaw
367       = new (GeomFill_GuideTrihedronAC) (Guide);
368     Handle(GeomFill_LocationGuide) Loc = 
369       new (GeomFill_LocationGuide) (TLaw);      
370     myLocation = new (BRepFill_ACRLaw) (mySpine, Loc);  
371   }
372   else {// trihedron by plane
373     if (KeepContact) 
374       myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation 
375     else 
376       myTrihedron = GeomFill_IsGuidePlan; // without rotation
377
378     Handle(GeomFill_GuideTrihedronPlan) TLaw = 
379       new (GeomFill_GuideTrihedronPlan) (Guide);    
380     Handle(GeomFill_LocationGuide) Loc = 
381       new (GeomFill_LocationGuide) (TLaw);
382     myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);  
383   }    
384   mySection.Nullify(); //It is required to relocalize the sections.
385 }
386
387 //=======================================================================
388 //function : Add
389 //purpose  : Add a Section
390 //=======================================================================
391  void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
392                               const Standard_Boolean WithContact,
393                               const Standard_Boolean WithCorrection) 
394
395   TopoDS_Vertex V;
396   V.Nullify();
397   Add(Profile, V, WithContact, WithCorrection);
398   ResetLoc();
399 }
400
401 //=======================================================================
402 //function : Add
403 //purpose  : Add a Section
404 //=======================================================================
405  void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
406                               const TopoDS_Vertex& Location,
407                               const Standard_Boolean WithContact,
408                               const Standard_Boolean WithCorrection) 
409 {
410  Delete(Profile); // No duplication
411  BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
412  mySeq.Append(S);
413  mySection.Nullify();
414  ResetLoc();
415 }
416
417 //=======================================================================
418 //function : SetLaw
419 //purpose  : Section + law of homothety
420 //=======================================================================
421  void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
422                                  const Handle(Law_Function)& L,
423                                  const Standard_Boolean WithContact,
424                                  const Standard_Boolean WithCorrection) 
425 {
426  TopoDS_Vertex V;
427  V.Nullify();
428  SetLaw( Profile, L, V, WithContact, WithCorrection);
429  ResetLoc();
430 }
431
432 //=======================================================================
433 //function : SetLaw
434 //purpose  :  Section + Law of homothety
435 //=======================================================================
436  void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
437                                  const Handle(Law_Function)& L,
438                                  const TopoDS_Vertex& Location,
439                                  const Standard_Boolean WithContact,
440                                  const Standard_Boolean WithCorrection) 
441 {
442   mySeq.Clear();
443   BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
444   S.Set(Standard_True);
445   mySeq.Append(S);
446   myLaw = L;
447   mySection.Nullify();
448   ResetLoc();
449 }
450
451 //=======================================================================
452 //function : Delete
453 //purpose  : Delete a section
454 //=======================================================================
455  void BRepFill_PipeShell::Delete(const TopoDS_Shape&  Profile)
456 {
457   Standard_Boolean isVertex = (Profile.ShapeType() == TopAbs_VERTEX);
458
459   Standard_Boolean Trouve=Standard_False;
460   Standard_Integer ii;
461   for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) {
462     Standard_Boolean found = Standard_False;
463     const TopoDS_Wire& aWire = mySeq.Value(ii).Wire();
464     if (isVertex)
465       {
466         TopExp_Explorer Explo(aWire, TopAbs_VERTEX);
467         for (; Explo.More(); Explo.Next())
468           if (Profile.IsSame(Explo.Current()))
469             found = Standard_True;
470       }
471     else if (Profile.IsSame(aWire))
472       found = Standard_True;
473     
474     if (found)
475       {
476         Trouve = Standard_True;
477         mySeq.Remove(ii);
478       }
479   }
480
481   if (Trouve) mySection.Nullify();
482   ResetLoc();
483 }
484
485
486 //=======================================================================
487 //function : IsReady
488 //purpose  : 
489 //=======================================================================
490  Standard_Boolean BRepFill_PipeShell::IsReady() const
491 {
492  return (mySeq.Length() != 0);
493 }
494 //=======================================================================
495 //function : GetStatus
496 //purpose  : 
497 //=======================================================================
498  GeomFill_PipeError BRepFill_PipeShell::GetStatus() const
499 {
500  return myStatus;
501 }
502
503
504 //=======================================================================
505 //function : SetTolerance
506 //purpose  :
507 //=======================================================================
508  void BRepFill_PipeShell::SetTolerance(const Standard_Real Tol3d  ,
509                                        const Standard_Real BoundTol, 
510                                        const Standard_Real TolAngular)
511 {
512  myTol3d = Tol3d;
513  myBoundTol =  BoundTol;
514  myTolAngular = TolAngular;
515 }
516
517 //=======================================================================
518 //function : SetTransition
519 //purpose  : Defines the mode of processing of corners
520 //=======================================================================
521  void BRepFill_PipeShell::SetTransition(const BRepFill_TransitionStyle Mode,
522                                         const Standard_Real Angmin,
523                                         const Standard_Real Angmax)
524 {
525  if (myTransition != Mode) 
526    mySection.Nullify(); //It is required to relocalize the sections.
527  myTransition = Mode;
528  angmin =  Angmin;
529  angmax = Angmax;
530 }  
531
532 //=======================================================================
533 //function : Simulate
534 //purpose  : Calculate N Sections
535 //=======================================================================
536  void BRepFill_PipeShell::Simulate(const Standard_Integer N, 
537                                    TopTools_ListOfShape& List)
538 {
539   // Preparation
540   Prepare();
541   List.Clear();
542
543   Standard_Real First, Last, Length, Delta, U, 
544                 US, DeltaS,FirstS;
545   Standard_Integer ii, NbL = myLocation->NbLaw();
546   Standard_Boolean Finis=Standard_False;
547   TopoDS_Shape W;
548   
549   // Calculate the parameters of digitalization
550   mySection->Law(1)->GetDomain(FirstS, Last);
551   DeltaS = Last - FirstS; 
552   myLocation->CurvilinearBounds(NbL,First, Length);
553   Delta = Length;
554   if (N>1) Delta /= (N-1);
555
556   myLocation->CurvilinearBounds(1,First, Last); // Initiation of Last
557   for (U=0.0, ii=1; !Finis ; U+=Delta) {
558     if (U >= Length) {
559       U = Length;
560       Finis = Standard_True;
561     }
562     else {
563       if (ii <  NbL) myLocation->CurvilinearBounds(NbL,First, Last);
564       if (U > Last) U = (Last+First)/2; // The edge is not skipped
565       if (U> First) ii++;
566     }
567     US = FirstS + (U/Length)*DeltaS;
568     // Calcul d'une section
569     mySection->D0(US, W);
570     myLocation->D0(U, W);
571     List.Append(W);
572   } 
573 }
574
575 //=======================================================================
576 //function : Build
577 //purpose  : Construct the Shell and the history
578 //=======================================================================
579  Standard_Boolean BRepFill_PipeShell::Build() 
580 {
581   Standard_Boolean Ok;
582   Standard_Real FirstS, LastS;
583   // 1) Preparation
584   Prepare();
585
586   if (myStatus != GeomFill_PipeOk) {
587     BRep_Builder B;
588     TopoDS_Shell Sh;
589     B.MakeShell(Sh); 
590     myShape = Sh; // Nullify
591     return Standard_False; 
592   }
593
594   // 2) Calculate myFirst and myLast
595   mySection->Law(1)->GetDomain(FirstS, LastS);
596   mySection->D0(FirstS, myFirst);
597   myLocation->D0(0, myFirst);
598   if (mySection->IsVClosed() && myLocation->IsClosed()) {
599       if (myLocation->IsG1(0)>=0) 
600         myLast = myFirst;
601       else {
602         myFirst.Nullify();
603         myLast.Nullify();
604       }
605   }
606   else {
607     Standard_Real Length;
608     myLocation->CurvilinearBounds(myLocation->NbLaw(), 
609                                   FirstS, Length);
610     mySection->D0(LastS,   myLast);
611     myLocation->D0(Length, myLast);
612     // eap 5 Jun 2002 occ332, myLast and myFirst must not share one TShape,
613     // tolerances of shapes built on them may be quite different
614     if (myFirst.IsPartner( myLast )) {
615       BRepBuilderAPI_Copy copy(myLast);
616       if (copy.IsDone()) 
617         myLast = copy.Shape();
618     }
619     // eap 5 Jun 2002 occ332, end modif
620   }
621 #if DRAW
622   if (Affich) {
623     DBRep::Set("PipeFirst", myFirst);
624     DBRep::Set("PipeLast",  myLast);
625   }
626 #endif
627
628   // 3) Construction
629   BRepFill_Sweep MkSw(mySection, myLocation, Standard_True);
630   MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
631   MkSw.SetAngularControl(angmin, angmax);
632   MkSw.SetBounds(TopoDS::Wire(myFirst), 
633                  TopoDS::Wire(myLast));
634   MkSw.Build(myTransition);
635
636   myStatus = myLocation->GetStatus();
637   Ok =  (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
638
639   if (Ok) {
640     myShape = MkSw.Shape();
641
642     TopoDS_Shape aBottomWire = myFirst;
643     TopoDS_Shape aTopWire    = myLast;
644
645     if(BuildBoundaries(MkSw, mySection, aBottomWire, aTopWire)) {
646       myFirst = aBottomWire;
647       myLast = aTopWire;
648     }
649     
650     if (mySection->IsUClosed())
651       {
652         TopExp_Explorer explo;
653         Standard_Boolean DegenFirst = Standard_True, DegenLast = Standard_True;
654
655         for (explo.Init(myFirst, TopAbs_EDGE); explo.More(); explo.Next())
656           {
657             const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
658             DegenFirst = DegenFirst && BRep_Tool::Degenerated(anEdge);
659           }
660
661         for (explo.Init(myLast, TopAbs_EDGE); explo.More(); explo.Next())
662           {
663             const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
664             DegenLast = DegenLast && BRep_Tool::Degenerated(anEdge);
665           }
666
667         if (DegenFirst && DegenLast)
668           myShape.Closed(Standard_True);
669       }
670
671     BuildHistory(MkSw);
672   }
673   else {
674     BRep_Builder B;
675     TopoDS_Shell Sh;
676     B.MakeShell(Sh); 
677     myShape = Sh; // Nullify
678     if (myStatus == GeomFill_PipeOk) myStatus = GeomFill_PipeNotOk;
679   }
680   return Ok;
681 }
682
683 //=======================================================================
684 //function : MakeSolid
685 //purpose  : 
686 //=======================================================================
687  Standard_Boolean BRepFill_PipeShell::MakeSolid() 
688
689   if (myShape.IsNull()) 
690     StdFail_NotDone::Raise("PipeShell is not built");
691   Standard_Boolean B = myShape.Closed();
692   BRep_Builder BS;
693
694   if (!B)
695     {
696       if(!myFirst.IsNull() && !myLast.IsNull()) {
697         B = (myFirst.Closed() && myLast.Closed());
698       }
699       if (B) {
700         // It is necessary to block the extremities 
701         B =  PerformPlan(myFirst);
702         if (B) {
703           B =  PerformPlan(myLast);
704           if (B) {
705             if (!myFirst.IsNull() && !IsSameOriented( myFirst, myShape ))
706               myFirst.Reverse();
707             if (!myLast.IsNull() && !IsSameOriented( myLast, myShape ))
708               myLast.Reverse();
709
710             if (!myFirst.IsNull())
711               BS.Add(myShape, TopoDS::Face(myFirst));
712             if (!myLast.IsNull())
713               BS.Add(myShape, TopoDS::Face(myLast));
714
715             myShape.Closed(Standard_True);
716           }
717         }
718       }
719     }
720
721   if (B) {
722    TopoDS_Solid solid;
723    BS.MakeSolid(solid);
724    BS.Add(solid,TopoDS::Shell(myShape));
725    BRepClass3d_SolidClassifier SC(solid);
726    SC.PerformInfinitePoint(Precision::Confusion());
727    if ( SC.State() == TopAbs_IN) {
728      BS.MakeSolid(solid);
729      myShape.Reverse();
730      BS.Add(solid,TopoDS::Shell(myShape));
731    }
732    myShape = solid;   
733    myShape.Closed(Standard_True);
734  }
735   return B;
736 }
737
738 //=======================================================================
739 //function : Shape
740 //purpose  : Return the result
741 //=======================================================================
742 const TopoDS_Shape& BRepFill_PipeShell::Shape() const
743 {
744   return myShape;
745 }
746
747 //=======================================================================
748 //function : FirstShape
749 //purpose  : Return the start section 
750 //=======================================================================
751 const TopoDS_Shape& BRepFill_PipeShell::FirstShape() const
752 {
753   return myFirst;
754 }
755
756 //=======================================================================
757 //function : LastShape
758 //purpose  : Return the end section 
759 //=======================================================================
760 const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
761 {
762  return myLast;
763 }
764
765 //=======================================================================
766 //function : Generated
767 //purpose  : 
768 //=======================================================================
769 //  void BRepFill_PipeShell::Generated(const TopoDS_Shape& ,
770 //                                  TopTools_ListOfShape& ) 
771 void BRepFill_PipeShell::Generated(const TopoDS_Shape&   theShape,
772                                    TopTools_ListOfShape& theList) 
773 {
774   //   Standard_NotImplemented::Raise("Generated:Pas Fait"); 
775   theList.Clear();
776
777   if(myGenMap.IsBound(theShape)) {
778     theList = myGenMap.Find(theShape);
779   } 
780 }
781
782 //=======================================================================
783 //function : Prepare
784 //purpose  : - Check that everything is ready
785 //           - Construct the law of section
786 //           - Construct the law of location if required
787 //           - Calculate First & Last
788 //=======================================================================
789  void BRepFill_PipeShell::Prepare() 
790 {
791   TopoDS_Wire theSect;
792   if (!IsReady()) StdFail_NotDone::Raise("PipeShell");
793   if (!myLocation.IsNull() && !mySection.IsNull()) return; // It is ready
794  
795   //Check set of section for right configuration of punctual sections
796   Standard_Integer i;
797   TopoDS_Iterator iter;;
798   for (i = 2; i <= mySeq.Length()-1; i++)
799     {
800       Standard_Boolean wdeg = Standard_True;
801       for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
802         {
803           const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
804           wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
805         }
806       if (wdeg)
807         Standard_Failure::Raise("Wrong usage of punctual sections");
808     }
809   if (mySeq.Length() <= 2)
810     {
811       Standard_Boolean wdeg = Standard_True;
812       for (i = 1; i <= mySeq.Length(); i++)
813         for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
814           {
815             const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
816             wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
817           }
818       if (wdeg)
819         Standard_Failure::Raise("Wrong usage of punctual sections");
820     }
821
822   // Construction of the law of location  
823   if(myLocation.IsNull()) 
824     {
825       switch(myTrihedron)
826         {
827         case GeomFill_IsCorrectedFrenet :
828           {
829             Handle(GeomFill_TrihedronLaw) TLaw = 
830               new (GeomFill_CorrectedFrenet) ();
831             Handle(GeomFill_CurveAndTrihedron) Loc = 
832               new (GeomFill_CurveAndTrihedron) (TLaw);
833             myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
834             break;
835           } 
836           default :
837             { // Not planned!
838               Standard_ConstructionError::Raise("PipeShell");
839             }
840         }
841     }  
842   
843   //Transformation of the law (Transition Management)
844   PerformTransition(myTransition, myLocation, angmin);
845
846   
847  // Construction of the section law
848   if (mySeq.Length() == 1) {
849     Standard_Real p1;
850     gp_Trsf aTrsf;
851     Place(mySeq(1), theSect, aTrsf, p1);
852     TopoDS_Wire aLocalShape = theSect;
853     if (mySeq(1).IsLaw())
854       mySection = new BRepFill_ShapeLaw(aLocalShape, myLaw);
855 //      mySection = new (BRepFill_ShapeLaw) (TopoDS_Wire(theSect), myLaw);
856     else 
857       mySection = new BRepFill_ShapeLaw(aLocalShape);
858 // mySection = new (BRepFill_ShapeLaw) (TopoDS::Wire(theSect));
859     }   
860   else 
861     {
862       TColStd_SequenceOfReal Param;
863       TopTools_SequenceOfShape WSeq;
864       GeomFill_SequenceOfTrsf Transformations;
865       //WSeq.Clear();
866       //Param.Clear();
867       Standard_Integer NbL = myLocation->NbLaw();
868       gp_Trsf aTrsf;
869       Standard_Real V1, V2, param;
870       myLocation->CurvilinearBounds(NbL, V1, V2);
871       V1 = 0.;
872       Standard_Integer ideb = 0, ifin = 0;
873 //      for (Standard_Integer iseq=1;iseq<=mySeq.Length();iseq++) {
874       Standard_Integer iseq;
875       for (iseq=1;iseq<=mySeq.Length();iseq++) {
876         Place(mySeq(iseq), theSect, aTrsf, param);
877         Param.Append(param);
878         WSeq.Append(theSect);
879 //      WSeq.Append(TopoDS::Wire(theSect));
880         Transformations.Append(aTrsf);
881         if (param==V1) ideb = iseq;
882         if (param==V2) ifin = iseq;
883       }
884       
885
886       // looping sections ?
887       if (myLocation->IsClosed()) {
888         if (ideb>0) {
889           // place the initial section at the final position 
890           Param.Append(V2);
891           WSeq.Append(WSeq(ideb));
892         }
893         else if (ifin>0) {
894           // place the final section at the initial position
895           Param.Append(V1);
896           WSeq.Append(WSeq(ifin));
897         }
898         else {
899           // it is necessary to find a medium section to impose by V1 and by V2
900           Standard_Real pmin = Param.Value(1), pmax = Param.Value(1);
901           TopoDS_Wire Wmin = TopoDS::Wire(WSeq.Value(1)), Wmax;
902           for (iseq=2;iseq<=WSeq.Length();iseq++) {
903             if (Param.Value(iseq)<pmin) {
904               pmin = Param.Value(iseq);
905               Wmin = TopoDS::Wire(WSeq.Value(iseq));
906             }
907             if (Param.Value(iseq)>pmax) {
908               pmax = Param.Value(iseq);
909               Wmax = TopoDS::Wire(WSeq.Value(iseq));
910             }
911           }
912           // medium section between Wmin and Wmax
913           TopoDS_Wire Wres;
914           Standard_Real dmin = Abs(pmin-V1);
915           Standard_Real dmax = Abs(pmax-V2);
916           if (ComputeSection(Wmin,Wmax,dmin,dmax,Wres)) {
917             // impose section Wres at the beginning and the end
918             Param.Append(V1);
919             WSeq.Append(Wres);
920             Param.Append(V2);
921             WSeq.Append(Wres);
922             
923           }
924           
925         }
926       }
927
928       // parse sections by increasing parameter
929       Standard_Boolean play_again = Standard_True;
930       while (play_again) {
931         play_again = Standard_False;
932         for (iseq=1;iseq<=WSeq.Length();iseq++) {
933           for (Standard_Integer jseq=iseq+1;jseq<=WSeq.Length();jseq++) {
934             if (Param.Value(iseq)>Param.Value(jseq)) {
935               Param.Exchange(iseq,jseq);
936               WSeq.Exchange(iseq,jseq);
937               play_again = Standard_True;
938             }
939           }
940         }
941       }
942
943 #ifdef DRAW
944   if ( Affich) {
945     char*  name = new char[100];
946     Standard_Integer NBSECT = 0;
947     for (Standard_Integer i=1;i<=WSeq.Length();i++) {
948       NBSECT++;
949       sprintf(name,"WSeq_%d",NBSECT);
950       DBRep::Set(name,TopoDS::Wire(WSeq.Value(i)));
951     }
952   }
953 #endif
954       
955       
956
957       //  Calculate work sections 
958       TopTools_SequenceOfShape WorkingSections;
959       WorkingSections.Clear();
960       TopTools_DataMapOfShapeListOfShape WorkingMap;
961       WorkingMap.Clear();
962       BRepFill_CompatibleWires Georges(WSeq);
963       Georges.SetPercent(0.1);
964       Georges.Perform(Standard_False);
965       if (Georges.IsDone()) {
966         WorkingSections = Georges.Shape();
967         WorkingMap = Georges.Generated();
968       }
969       else {
970         Standard_ConstructionError::Raise("PipeShell : uncompatible wires");
971       }
972       mySection = new (BRepFill_NSections) (WorkingSections,Transformations,Param,V1,V2);
973       
974     }// else
975
976   //  modify the law of location if contact
977   if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
978       || (myTrihedron == GeomFill_IsGuideACWithContact) )  {
979     Standard_Real fs, f, l, Delta, Length;
980     Handle(GeomFill_LocationGuide) Loc;
981     Handle(GeomFill_SectionLaw) Sec = mySection->ConcatenedLaw();
982     myLocation->CurvilinearBounds(myLocation->NbLaw(), f, Length);
983     Sec->GetDomain(fs,l);
984     Delta = (l-fs)/Length;
985
986     Standard_Real angle, old_angle = 0;
987     for (Standard_Integer ipath=1; ipath<=myLocation->NbLaw(); ipath++) {
988       myLocation->CurvilinearBounds(ipath, f, l);
989       Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(ipath));
990       Loc->Set(Sec, Standard_True, fs + f*Delta, fs + l*Delta,
991                old_angle, angle); // force the rotation 
992       old_angle = angle;
993     }      
994   }
995
996   myStatus = myLocation->GetStatus();
997 }
998
999 //=======================================================================
1000 //function : Place
1001 //purpose  : Implement a Section in the local refernce frame
1002 //           and return its parameter on the trajectory
1003 //=======================================================================
1004 void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
1005                                TopoDS_Wire& W,
1006                                gp_Trsf& aTrsf,
1007                                Standard_Real& param)
1008 {
1009   BRepFill_SectionPlacement Place(myLocation, 
1010                                   Sec.Wire(),
1011                                   Sec.Vertex(),
1012                                   Sec.WithContact(),
1013                                   Sec.WithCorrection());
1014   W =  Sec.Wire();
1015   aTrsf = Place.Transformation();
1016   TopLoc_Location Loc2(Place.Transformation()), Loc1;
1017   Loc1 = W.Location();
1018   W.Location(Loc2.Multiplied(Loc1));
1019   param = Place.AbscissaOnPath();
1020 }
1021
1022
1023 //=======================================================================
1024 //function : ResetLoc
1025 //purpose  : Remove references to the sections in the laws of location
1026 //=======================================================================
1027  void BRepFill_PipeShell::ResetLoc() 
1028 {
1029   if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1030       || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1031     Handle(GeomFill_LocationGuide) Loc;
1032     for (Standard_Integer isec=1; isec<=myLocation->NbLaw(); isec++) { 
1033       Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(isec));
1034       Loc->EraseRotation();// remove the rotation       
1035     }    
1036   }
1037 }
1038
1039 //=======================================================================
1040 //function : BuildHistory
1041 //purpose  : Builds history for edges of spine, 
1042 //           for built bottom shape of sweep,
1043 //           for boundary vertices of bottom shape of sweep,
1044 //           for boundary profiles
1045 //=======================================================================
1046 void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep) 
1047 {
1048   Handle(TopTools_HArray2OfShape) aFaces = theSweep.SubShape();
1049   Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1050   Handle(TopTools_HArray2OfShape) aUEdges = theSweep.InterFaces();
1051   Standard_Integer i = 0, j = 0;
1052   Standard_Boolean bPrevModified = Standard_False;
1053
1054   for(i = 1; i <= mySection->NbLaw(); i++) {
1055     if((!aVEdges->Value(i, 1).IsNull()) && (aVEdges->Value(i, 1).ShapeType() == TopAbs_FACE)) {
1056       bPrevModified = Standard_True;
1057       break;
1058     }
1059   }
1060
1061   for(j = myLocation->NbLaw(); j >= 1; j--) {
1062     TopTools_ListOfShape aListOfFace;
1063
1064     if(bPrevModified) {
1065       for(i = 1; i <= mySection->NbLaw(); i++) {
1066         Standard_Integer lessindex = j + 1;
1067         lessindex = (lessindex > myLocation->NbLaw()) ? 1 : lessindex;
1068
1069         if((!aVEdges->Value(i, lessindex).IsNull()) && (aVEdges->Value(i, lessindex).ShapeType() == TopAbs_FACE)) {
1070           aListOfFace.Append(aVEdges->Value(i, lessindex));
1071           const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1072
1073           if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1074             UpdateMap(aBottomEdge, aVEdges->Value(i, lessindex), myGenMap);
1075           }
1076         }
1077       }
1078     }
1079     bPrevModified = Standard_False;
1080
1081     for(i = 1; i <= mySection->NbLaw(); i++) {
1082       if((!aVEdges->Value(i, j).IsNull()) && (aVEdges->Value(i, j).ShapeType() == TopAbs_FACE)) {
1083         aListOfFace.Append(aVEdges->Value(i, j));
1084         bPrevModified = Standard_True;
1085
1086         const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1087
1088         if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1089           UpdateMap(aBottomEdge, aVEdges->Value(i, j), myGenMap);
1090         }
1091       }
1092
1093       if(aFaces->Value(i, j).ShapeType() == TopAbs_FACE) {
1094         aListOfFace.Append(aFaces->Value(i, j));
1095         const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, 1);
1096
1097         if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1098           UpdateMap(aBottomEdge, aFaces->Value(i, j), myGenMap);
1099         }
1100       }
1101     }
1102
1103     if(!myGenMap.IsBound(myLocation->Edge(j)))
1104       myGenMap.Bind(myLocation->Edge(j), aListOfFace);
1105     else
1106       myGenMap.ChangeFind(myLocation->Edge(j)).Append(aListOfFace);
1107
1108     // build history for free booundaries.begin
1109     if(!mySection->IsUClosed()) {
1110       TopoDS_Compound aFaceComp;
1111       BRep_Builder aB;
1112       aB.MakeCompound(aFaceComp);
1113       TopTools_ListIteratorOfListOfShape anIt(aListOfFace);
1114
1115       for(; anIt.More(); anIt.Next()) {
1116         aB.Add(aFaceComp, anIt.Value());
1117       }
1118       TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
1119       TopExp::MapShapesAndAncestors(aFaceComp, TopAbs_EDGE, TopAbs_FACE, aMapEF);
1120       Standard_Integer eit = 0;
1121
1122       for(eit = aUEdges->LowerRow(); eit <= aUEdges->UpperRow(); eit++) {
1123         const TopoDS_Shape& aShape = aUEdges->Value(eit, j);
1124
1125         if(aMapEF.Contains(aShape)) {
1126           const TopTools_ListOfShape& aList = aMapEF.FindFromKey(aShape);
1127
1128           if(aList.Extent() < 2) {
1129             UpdateMap(myLocation->Edge(j), aShape, myGenMap);
1130
1131             TopoDS_Shape aGenVertex;
1132             TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
1133             
1134             for(i = 1; i <= mySection->NbLaw(); i++) {
1135               const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1136
1137               if((!aBottomEdge.IsNull()) && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1138                 TopExp::MapShapesAndAncestors(aBottomEdge, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1139               }
1140             }
1141             const TopoDS_Shape& aFreeEdge = aUEdges->Value(eit, aUEdges->LowerCol());
1142             TopExp::MapShapesAndAncestors(aFreeEdge, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
1143             TopExp_Explorer anExpV(aFreeEdge, TopAbs_VERTEX);
1144
1145             for(; anExpV.More(); anExpV.Next()) {
1146               if(aMapVE.Contains(anExpV.Current())) {
1147                 const TopTools_ListOfShape& aListOfV = aMapVE.FindFromKey(anExpV.Current());
1148
1149                 if(aListOfV.Extent() >= 2) {
1150                   aGenVertex = anExpV.Current();
1151                 }
1152               }
1153             }
1154
1155             if(!aGenVertex.IsNull()) {
1156               UpdateMap(aGenVertex, aShape, myGenMap);
1157             }
1158           }
1159         }
1160       }
1161       // end for(eit = aUEdges->LowerRow...
1162     }
1163     // build history for free booundaries.end
1164   }
1165
1166   // build history for boundary section wires. begin
1167
1168   if(!mySeq.IsEmpty()) {
1169     Standard_Integer iseq;
1170     TopoDS_Wire aSect;
1171     gp_Trsf aTrsf;
1172     Standard_Real param = 0., aparmin = RealLast(), aparmax = -RealLast();
1173     Standard_Integer ideb = 1, ifin = mySeq.Length();
1174
1175     for (iseq = 1;iseq <= mySeq.Length(); iseq++) {
1176       Place(mySeq(iseq), aSect, aTrsf, param);
1177
1178       if(param < aparmin) {
1179         ideb = iseq;
1180         aparmin = param;
1181       }
1182
1183       if(param > aparmax) {
1184         ifin = iseq;
1185         aparmax = param;
1186       }
1187     }
1188     
1189     UpdateMap(mySeq(ideb).Wire(), myFirst, myGenMap);
1190     UpdateMap(mySeq(ifin).Wire(), myLast, myGenMap);
1191   }
1192   // build history for boundary section wires. end
1193 }
1194
1195 // ---------------------------------------------------------------------------------
1196 // static function: UpdateMap
1197 // purpose:
1198 // ---------------------------------------------------------------------------------
1199 Standard_Boolean UpdateMap(const TopoDS_Shape&                 theKey,
1200                            const TopoDS_Shape&                 theValue,
1201                            TopTools_DataMapOfShapeListOfShape& theMap) {
1202
1203   if(!theMap.IsBound(theKey)) {
1204     TopTools_ListOfShape thelist;
1205     theMap.Bind(theKey, thelist);
1206   }
1207   TopTools_ListOfShape& aList = theMap.ChangeFind(theKey);
1208   TopTools_ListIteratorOfListOfShape anIt(aList);
1209   Standard_Boolean found = Standard_False;
1210
1211   for(; anIt.More(); anIt.Next()) {
1212     if(theValue.IsSame(anIt.Value())) {
1213       found = Standard_True;
1214       break;
1215     }
1216   }
1217
1218   if(!found)
1219     aList.Append(theValue);
1220   return !found;
1221 }
1222
1223 // ---------------------------------------------------------------------------------
1224 // static function: BuildBoundaries
1225 // purpose:
1226 // ---------------------------------------------------------------------------------
1227 Standard_Boolean BuildBoundaries(const BRepFill_Sweep&               theSweep,
1228                                  const Handle(BRepFill_SectionLaw)&  theSection,
1229                                  TopoDS_Shape&                       theBottom,
1230                                  TopoDS_Shape&                       theTop) {
1231   
1232   TopoDS_Wire aBottomWire;
1233   TopoDS_Wire aTopWire;
1234   BRep_Builder aB;
1235   aB.MakeWire(aBottomWire);
1236   aB.MakeWire(aTopWire);
1237   Standard_Boolean bfoundbottom = Standard_False;
1238   Standard_Boolean bfoundtop = Standard_False;
1239   Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1240   Standard_Integer i = 0;
1241   Standard_Boolean bAllSame = Standard_True;
1242
1243   for(i = 1; i <= theSection->NbLaw(); i++) {
1244     const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1245
1246     if(!aBottomEdge.IsNull() && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1247       aB.Add(aBottomWire, aBottomEdge);
1248       bfoundbottom = Standard_True;
1249     }
1250     const TopoDS_Shape& aTopEdge = aVEdges->Value(i, aVEdges->UpperCol());
1251
1252     if(!aTopEdge.IsNull() && (aTopEdge.ShapeType() == TopAbs_EDGE)) {
1253       aB.Add(aTopWire, aTopEdge);
1254       bfoundtop = Standard_True;
1255     }
1256
1257     if(!aBottomEdge.IsNull() && !aTopEdge.IsNull() && !aBottomEdge.IsSame(aTopEdge))
1258       bAllSame = Standard_False;
1259   }
1260
1261   if(theSection->IsUClosed()) {
1262     aBottomWire.Closed(Standard_True);
1263     aTopWire.Closed(Standard_True);
1264   }
1265
1266   if(bfoundbottom) {
1267     theBottom = aBottomWire;
1268   }
1269
1270   if(bfoundtop) {
1271     theTop  = aTopWire;
1272   }
1273
1274   if(bAllSame && bfoundbottom && bfoundtop)
1275     theTop = theBottom;
1276
1277   return bfoundbottom || bfoundtop;
1278 }