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