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