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