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