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