0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[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,Standard_Transient)
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
389   Handle(BRepAdaptor_HCompCurve) Guide = new (BRepAdaptor_HCompCurve) (TheGuide);
390
391   if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa
392     if (KeepContact == BRepFill_Contact ||
393         KeepContact == BRepFill_ContactOnBorder) 
394       myTrihedron = GeomFill_IsGuideACWithContact; // with rotation 
395     else
396       myTrihedron = GeomFill_IsGuideAC; // without rotation 
397       
398     Handle(GeomFill_GuideTrihedronAC) TLaw
399       = new (GeomFill_GuideTrihedronAC) (Guide);
400     Handle(GeomFill_LocationGuide) Loc = 
401       new (GeomFill_LocationGuide) (TLaw);      
402     myLocation = new (BRepFill_ACRLaw) (mySpine, Loc);  
403   }
404   else {// trihedron by plane
405     if (KeepContact == BRepFill_Contact ||
406         KeepContact == BRepFill_ContactOnBorder) 
407       myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation 
408     else 
409       myTrihedron = GeomFill_IsGuidePlan; // without rotation
410
411     Handle(GeomFill_GuideTrihedronPlan) TLaw = 
412       new (GeomFill_GuideTrihedronPlan) (Guide);    
413     Handle(GeomFill_LocationGuide) Loc = 
414       new (GeomFill_LocationGuide) (TLaw);
415     myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);  
416   }    
417   mySection.Nullify(); //It is required to relocalize the sections.
418 }
419
420
421 //=======================================================================
422 //function : SetMaxDegree
423 //purpose  : 
424 //=======================================================================
425 void BRepFill_PipeShell::SetMaxDegree(const Standard_Integer NewMaxDegree)
426 {
427   myMaxDegree = NewMaxDegree;
428 }
429
430 //=======================================================================
431 //function : SetMaxSegments
432 //purpose  : 
433 //=======================================================================
434 void BRepFill_PipeShell::SetMaxSegments(const Standard_Integer NewMaxSegments)
435 {
436   myMaxSegments = NewMaxSegments;
437 }
438
439 //=======================================================================
440 //function : SetForceApproxC1
441 //purpose  : Set the flag that indicates attempt to approximate
442 //           a C1-continuous surface if a swept surface proved
443 //           to be C0.
444 //=======================================================================
445 void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1)
446 {
447   myForceApproxC1 = ForceApproxC1;
448 }
449
450 //=======================================================================
451 //function : Add
452 //purpose  : Add a Section
453 //=======================================================================
454  void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
455                               const Standard_Boolean WithContact,
456                               const Standard_Boolean WithCorrection) 
457
458   TopoDS_Vertex V;
459   V.Nullify();
460   Add(Profile, V, WithContact, WithCorrection);
461   ResetLoc();
462 }
463
464 //=======================================================================
465 //function : Add
466 //purpose  : Add a Section
467 //=======================================================================
468  void BRepFill_PipeShell::Add(const TopoDS_Shape& Profile,
469                               const TopoDS_Vertex& Location,
470                               const Standard_Boolean WithContact,
471                               const Standard_Boolean WithCorrection) 
472 {
473  DeleteProfile(Profile); // No duplication
474  if (myIsAutomaticLaw)
475  {
476    mySeq.Clear();
477    BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
478    S.Set(Standard_True);
479    mySeq.Append(S);
480    mySection.Nullify();
481    ResetLoc();
482
483    Handle(GeomFill_LocationGuide) Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(1));
484    Handle(TColgp_HArray1OfPnt2d) ParAndRad;
485    Loc->ComputeAutomaticLaw(ParAndRad);
486    
487    //Compuite initial width of section (this will be 1.)
488    GProp_GProps GlobalProps;
489    BRepGProp::LinearProperties(Profile, GlobalProps);
490    gp_Pnt BaryCenter = GlobalProps.CentreOfMass();
491
492    TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), Standard_True); //only plane
493    Handle(Geom_Surface) thePlane = BRep_Tool::Surface(ProfileFace);
494    Handle(GeomAdaptor_HSurface) GAHplane = new GeomAdaptor_HSurface(thePlane);
495    IntCurveSurface_HInter Intersector;
496    Handle(Adaptor3d_HCurve) aHCurve [2];
497    aHCurve[0] = Loc->GetCurve();
498    aHCurve[1] = Loc->Guide();
499    gp_Pnt PointsOnSpines [2];
500    Standard_Integer i, j;
501
502    for (i = 0; i < 2; i++)
503    {
504      Intersector.Perform(aHCurve[i], GAHplane);
505      Standard_Real MinDist = RealLast();
506      for (j = 1; j <= Intersector.NbPoints(); j++)
507      {
508        gp_Pnt aPint = Intersector.Point(j).Pnt();
509        Standard_Real aDist = BaryCenter.Distance(aPint);
510        if (aDist < MinDist)
511        {
512          MinDist = aDist;
513          PointsOnSpines[i] = aPint;
514        }
515      }
516    }
517
518    //Correct <ParAndRad> according to <InitialWidth>
519    Standard_Real InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]);
520    Standard_Integer NbParRad = ParAndRad->Upper();
521    for (i = 1; i <= NbParRad; i++)
522    {
523      gp_Pnt2d aParRad = ParAndRad->Value(i);
524      aParRad.SetY( aParRad.Y() / InitialWidth );
525      ParAndRad->SetValue(i, aParRad);
526    }
527   
528    myLaw = new Law_Interpol();
529    
530    Standard_Boolean IsPeriodic =
531      (Abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion());
532
533    (Handle(Law_Interpol)::DownCast(myLaw))->Set(ParAndRad->Array1(), IsPeriodic);
534  }
535  else
536  {
537    BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
538    mySeq.Append(S);
539    mySection.Nullify();
540    ResetLoc();
541  }
542 }
543
544 //=======================================================================
545 //function : SetLaw
546 //purpose  : Section + law of homothety
547 //=======================================================================
548  void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
549                                  const Handle(Law_Function)& L,
550                                  const Standard_Boolean WithContact,
551                                  const Standard_Boolean WithCorrection) 
552 {
553  TopoDS_Vertex V;
554  V.Nullify();
555  SetLaw( Profile, L, V, WithContact, WithCorrection);
556  ResetLoc();
557 }
558
559 //=======================================================================
560 //function : SetLaw
561 //purpose  :  Section + Law of homothety
562 //=======================================================================
563  void BRepFill_PipeShell::SetLaw(const TopoDS_Shape& Profile,
564                                  const Handle(Law_Function)& L,
565                                  const TopoDS_Vertex& Location,
566                                  const Standard_Boolean WithContact,
567                                  const Standard_Boolean WithCorrection) 
568 {
569   mySeq.Clear();
570   BRepFill_Section S (Profile, Location, WithContact, WithCorrection);
571   S.Set(Standard_True);
572   mySeq.Append(S);
573   myLaw = L;
574   mySection.Nullify();
575   ResetLoc();
576 }
577
578 //=======================================================================
579 //function : Delete
580 //purpose  : Delete a section
581 //=======================================================================
582  void BRepFill_PipeShell::DeleteProfile(const TopoDS_Shape&  Profile)
583 {
584   Standard_Boolean Trouve=Standard_False;
585   Standard_Integer ii;
586   for (ii=1; ii<=mySeq.Length() && !Trouve; ii++) {
587     const TopoDS_Shape& aSection = mySeq.Value(ii).OriginalShape();
588     if (Profile.IsSame(aSection))
589     {
590       Trouve = Standard_True;
591       mySeq.Remove(ii);
592     }
593   }
594
595   if (Trouve) mySection.Nullify();
596   ResetLoc();
597 }
598
599
600 //=======================================================================
601 //function : IsReady
602 //purpose  : 
603 //=======================================================================
604  Standard_Boolean BRepFill_PipeShell::IsReady() const
605 {
606  return (mySeq.Length() != 0);
607 }
608 //=======================================================================
609 //function : GetStatus
610 //purpose  : 
611 //=======================================================================
612  GeomFill_PipeError BRepFill_PipeShell::GetStatus() const
613 {
614  return myStatus;
615 }
616
617
618 //=======================================================================
619 //function : SetTolerance
620 //purpose  :
621 //=======================================================================
622  void BRepFill_PipeShell::SetTolerance(const Standard_Real Tol3d  ,
623                                        const Standard_Real BoundTol, 
624                                        const Standard_Real TolAngular)
625 {
626  myTol3d = Tol3d;
627  myBoundTol =  BoundTol;
628  myTolAngular = TolAngular;
629 }
630
631 //=======================================================================
632 //function : SetTransition
633 //purpose  : Defines the mode of processing of corners
634 //=======================================================================
635  void BRepFill_PipeShell::SetTransition(const BRepFill_TransitionStyle Mode,
636                                         const Standard_Real Angmin,
637                                         const Standard_Real Angmax)
638 {
639  if (myTransition != Mode) 
640    mySection.Nullify(); //It is required to relocalize the sections.
641  myTransition = Mode;
642  angmin =  Angmin;
643  angmax = Angmax;
644 }  
645
646 //=======================================================================
647 //function : Simulate
648 //purpose  : Calculate N Sections
649 //=======================================================================
650  void BRepFill_PipeShell::Simulate(const Standard_Integer N, 
651                                    TopTools_ListOfShape& List)
652 {
653   // Preparation
654   Prepare();
655   List.Clear();
656
657   Standard_Real First, Last, Length, Delta, U, 
658                 US, DeltaS,FirstS;
659   Standard_Integer ii, NbL = myLocation->NbLaw();
660   Standard_Boolean Finis=Standard_False;
661   TopoDS_Shape W;
662   
663   // Calculate the parameters of digitalization
664   mySection->Law(1)->GetDomain(FirstS, Last);
665   DeltaS = Last - FirstS; 
666   myLocation->CurvilinearBounds(NbL,First, Length);
667   Delta = Length;
668   if (N>1) Delta /= (N-1);
669
670   myLocation->CurvilinearBounds(1,First, Last); // Initiation of Last
671   for (U=0.0, ii=1; !Finis ; U+=Delta) {
672     if (U >= Length) {
673       U = Length;
674       Finis = Standard_True;
675     }
676     else {
677       if (ii <  NbL) myLocation->CurvilinearBounds(NbL,First, Last);
678       if (U > Last) U = (Last+First)/2; // The edge is not skipped
679       if (U> First) ii++;
680     }
681     US = FirstS + (U/Length)*DeltaS;
682     // Calcul d'une section
683     mySection->D0(US, W);
684     myLocation->D0(U, W);
685     List.Append(W);
686   } 
687 }
688
689 //=======================================================================
690 //function : Build
691 //purpose  : Construct the Shell and the history
692 //=======================================================================
693  Standard_Boolean BRepFill_PipeShell::Build()
694 {
695   Standard_Boolean Ok;
696   Standard_Real FirstS, LastS;
697   // 1) Preparation
698   Prepare();
699
700   if (myStatus != GeomFill_PipeOk) {
701     BRep_Builder B;
702     TopoDS_Shell Sh;
703     B.MakeShell(Sh); 
704     myShape = Sh; // Nullify
705     return Standard_False; 
706   }
707
708   // 2) Calculate myFirst and myLast
709   mySection->Law(1)->GetDomain(FirstS, LastS);
710   mySection->D0(FirstS, myFirst);
711   myLocation->D0(0, myFirst);
712   if (mySection->IsVClosed() && myLocation->IsClosed()) {
713       if (myLocation->IsG1(0)>=0) 
714         myLast = myFirst;
715       else {
716         myFirst.Nullify();
717         myLast.Nullify();
718       }
719   }
720   else {
721     Standard_Real Length;
722     myLocation->CurvilinearBounds(myLocation->NbLaw(), 
723                                   FirstS, Length);
724     mySection->D0(LastS,   myLast);
725     myLocation->D0(Length, myLast);
726     // eap 5 Jun 2002 occ332, myLast and myFirst must not share one TShape,
727     // tolerances of shapes built on them may be quite different
728     if (myFirst.IsPartner( myLast )) {
729       BRepBuilderAPI_Copy copy(myLast);
730       if (copy.IsDone()) 
731         myLast = copy.Shape();
732     }
733     // eap 5 Jun 2002 occ332, end modif
734   }
735 #if DRAW
736   if (Affich) {
737     DBRep::Set("PipeFirst", myFirst);
738     DBRep::Set("PipeLast",  myLast);
739   }
740 #endif
741
742   // 3) Construction
743   BRepFill_Sweep MkSw(mySection, myLocation, Standard_True);
744   MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular);
745   MkSw.SetAngularControl(angmin, angmax);
746   MkSw.SetForceApproxC1(myForceApproxC1);
747   MkSw.SetBounds(TopoDS::Wire(myFirst),
748                  TopoDS::Wire(myLast));
749
750   GeomAbs_Shape theContinuity = GeomAbs_C2;
751   if (myTrihedron == GeomFill_IsDiscreteTrihedron)
752     theContinuity = GeomAbs_C0;
753   TopTools_MapOfShape Dummy;
754   BRepFill_DataMapOfShapeHArray2OfShape Dummy2;
755   BRepFill_DataMapOfShapeHArray2OfShape Dummy3;
756   MkSw.Build(Dummy, Dummy2, Dummy3, myTransition, theContinuity,
757              GeomFill_Location, myMaxDegree, myMaxSegments);
758
759   myStatus = myLocation->GetStatus();
760   Ok =  (MkSw.IsDone() && (myStatus == GeomFill_PipeOk));
761
762   if (Ok) {
763     myShape = MkSw.Shape();
764     myErrorOnSurf = MkSw.ErrorOnSurface();
765
766     TopoDS_Shape aBottomWire = myFirst;
767     TopoDS_Shape aTopWire    = myLast;
768
769     if(BuildBoundaries(MkSw, mySection, aBottomWire, aTopWire)) {
770       myFirst = aBottomWire;
771       myLast = aTopWire;
772     }
773     
774     if (mySection->IsUClosed())
775       {
776         TopExp_Explorer explo;
777         Standard_Boolean DegenFirst = Standard_True, DegenLast = Standard_True;
778
779         for (explo.Init(myFirst, TopAbs_EDGE); explo.More(); explo.Next())
780           {
781             const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
782             DegenFirst = DegenFirst && BRep_Tool::Degenerated(anEdge);
783           }
784
785         for (explo.Init(myLast, TopAbs_EDGE); explo.More(); explo.Next())
786           {
787             const TopoDS_Edge& anEdge = TopoDS::Edge(explo.Current());
788             DegenLast = DegenLast && BRep_Tool::Degenerated(anEdge);
789           }
790
791         if (DegenFirst && DegenLast)
792           myShape.Closed(Standard_True);
793       }
794
795     BuildHistory(MkSw);
796   }
797   else {
798     BRep_Builder B;
799     TopoDS_Shell Sh;
800     B.MakeShell(Sh); 
801     myShape = Sh; // Nullify
802     if (myStatus == GeomFill_PipeOk) myStatus = GeomFill_PipeNotOk;
803   }
804   return Ok;
805 }
806
807 //=======================================================================
808 //function : MakeSolid
809 //purpose  : 
810 //=======================================================================
811  Standard_Boolean BRepFill_PipeShell::MakeSolid() 
812
813   if (myShape.IsNull()) 
814     throw StdFail_NotDone("PipeShell is not built");
815   Standard_Boolean B = myShape.Closed();
816   BRep_Builder BS;
817
818   if (!B)
819     {
820       if(!myFirst.IsNull() && !myLast.IsNull()) {
821         B = (myFirst.Closed() && myLast.Closed());
822       }
823       if (B) {
824         // It is necessary to block the extremities 
825         B =  PerformPlan(myFirst);
826         if (B) {
827           B =  PerformPlan(myLast);
828           if (B) {
829             if (!myFirst.IsNull() && !IsSameOriented( myFirst, myShape ))
830               myFirst.Reverse();
831             if (!myLast.IsNull() && !IsSameOriented( myLast, myShape ))
832               myLast.Reverse();
833
834             if (!myFirst.IsNull())
835               BS.Add(myShape, TopoDS::Face(myFirst));
836             if (!myLast.IsNull())
837               BS.Add(myShape, TopoDS::Face(myLast));
838
839             myShape.Closed(Standard_True);
840           }
841         }
842       }
843     }
844
845   if (B) {
846    TopoDS_Solid solid;
847    BS.MakeSolid(solid);
848    BS.Add(solid,TopoDS::Shell(myShape));
849    BRepClass3d_SolidClassifier SC(solid);
850    SC.PerformInfinitePoint(Precision::Confusion());
851    if ( SC.State() == TopAbs_IN) {
852      BS.MakeSolid(solid);
853      myShape.Reverse();
854      BS.Add(solid,TopoDS::Shell(myShape));
855    }
856    myShape = solid;   
857    myShape.Closed(Standard_True);
858  }
859   return B;
860 }
861
862 //=======================================================================
863 //function : Shape
864 //purpose  : Return the result
865 //=======================================================================
866 const TopoDS_Shape& BRepFill_PipeShell::Shape() const
867 {
868   return myShape;
869 }
870
871 //=======================================================================
872 //function : ErrorOnSurface
873 //purpose  : 
874 //=======================================================================
875
876 Standard_Real BRepFill_PipeShell::ErrorOnSurface() const 
877 {
878   return myErrorOnSurf;
879 }
880
881 //=======================================================================
882 //function : FirstShape
883 //purpose  : Return the start section 
884 //=======================================================================
885 const TopoDS_Shape& BRepFill_PipeShell::FirstShape() const
886 {
887   return myFirst;
888 }
889
890 //=======================================================================
891 //function : LastShape
892 //purpose  : Return the end section 
893 //=======================================================================
894 const TopoDS_Shape& BRepFill_PipeShell::LastShape() const
895 {
896  return myLast;
897 }
898
899 //=======================================================================
900 //function : Generated
901 //purpose  : 
902 //=======================================================================
903 void BRepFill_PipeShell::Generated(const TopoDS_Shape&   theShape,
904                                    TopTools_ListOfShape& theList) 
905 {
906   theList.Clear();
907
908   if(myGenMap.IsBound(theShape)) {
909     theList = myGenMap.Find(theShape);
910   }
911 }
912
913 //=======================================================================
914 //function : Prepare
915 //purpose  : - Check that everything is ready
916 //           - Construct the law of section
917 //           - Construct the law of location if required
918 //           - Calculate First & Last
919 //=======================================================================
920  void BRepFill_PipeShell::Prepare() 
921 {
922   WSeq.Clear();
923   myEdgeNewEdges.Clear();
924   
925   TopoDS_Wire theSect;
926   if (!IsReady()) throw StdFail_NotDone("PipeShell");
927   if (!myLocation.IsNull() && !mySection.IsNull()) return; // It is ready
928  
929   //Check set of section for right configuration of punctual sections
930   Standard_Integer i;
931   TopoDS_Iterator iter;
932   for (i = 2; i <= mySeq.Length()-1; i++)
933     {
934       Standard_Boolean wdeg = Standard_True;
935       for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
936         {
937           const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
938           wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
939         }
940       if (wdeg)
941         throw Standard_Failure("Wrong usage of punctual sections");
942     }
943   if (mySeq.Length() <= 2)
944     {
945       Standard_Boolean wdeg = Standard_True;
946       for (i = 1; i <= mySeq.Length(); i++)
947         for (iter.Initialize(mySeq(i).Wire()); iter.More(); iter.Next())
948           {
949             const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value());
950             wdeg = wdeg && (BRep_Tool::Degenerated(anEdge));
951           }
952       if (wdeg)
953         throw Standard_Failure("Wrong usage of punctual sections");
954     }
955
956   // Construction of the law of location  
957   if(myLocation.IsNull()) 
958     {
959       switch(myTrihedron)
960         {
961         case GeomFill_IsCorrectedFrenet :
962           {
963             Handle(GeomFill_TrihedronLaw) TLaw = 
964               new (GeomFill_CorrectedFrenet) ();
965             Handle(GeomFill_CurveAndTrihedron) Loc = 
966               new (GeomFill_CurveAndTrihedron) (TLaw);
967             myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc);
968             break;
969           } 
970           default :
971             { // Not planned!
972               throw Standard_ConstructionError("PipeShell");
973             }
974         }
975     }  
976   
977   //Transformation of the law (Transition Management)
978   PerformTransition(myTransition, myLocation, angmin);
979
980   
981  // Construction of the section law
982   if (mySeq.Length() == 1) {
983     Standard_Real p1;
984     gp_Trsf aTrsf;
985     Place(mySeq(1), theSect, aTrsf, p1);
986     TopoDS_Wire aLocalShape = theSect;
987     if (mySeq(1).IsLaw())
988       mySection = new BRepFill_ShapeLaw(aLocalShape, myLaw);
989 //      mySection = new (BRepFill_ShapeLaw) (TopoDS_Wire(theSect), myLaw);
990     else 
991       mySection = new BRepFill_ShapeLaw(aLocalShape);
992 // mySection = new (BRepFill_ShapeLaw) (TopoDS::Wire(theSect));
993     
994     WSeq.Append(theSect);
995     //Simple case of single section
996     myIndOfSec.Append(1);
997     TopoDS_Iterator itw(theSect);
998     for (; itw.More(); itw.Next())
999     {
1000       const TopoDS_Shape& anEdge = itw.Value();
1001       TopTools_ListOfShape Elist;
1002       Elist.Append(anEdge);
1003       myEdgeNewEdges.Bind(anEdge, Elist);
1004     }
1005     ///////////////////////////////
1006   }   
1007   else 
1008   {
1009     TColStd_SequenceOfReal Param;
1010     TColStd_SequenceOfInteger IndSec;
1011     GeomFill_SequenceOfTrsf Transformations;
1012     Standard_Integer NbL = myLocation->NbLaw();
1013     gp_Trsf aTrsf;
1014     Standard_Real V1, V2, param;
1015     myLocation->CurvilinearBounds(NbL, V1, V2);
1016     V1 = 0.;
1017     Standard_Integer ideb = 0, ifin = 0;
1018     Standard_Integer iseq;
1019     for (iseq = 1; iseq <= mySeq.Length(); iseq++) {
1020       IndSec.Append(iseq);
1021       Place(mySeq(iseq), theSect, aTrsf, param);
1022       Param.Append(param);
1023       WSeq.Append(theSect);
1024       Transformations.Append(aTrsf);
1025       if (param==V1) ideb = iseq;
1026       if (param==V2) ifin = iseq;
1027     }
1028     
1029     
1030     // looping sections ?
1031     if (myLocation->IsClosed()) {
1032       if (ideb>0) {
1033         // place the initial section at the final position 
1034         Param.Append(V2);
1035         WSeq.Append(WSeq(ideb));
1036       }
1037       else if (ifin>0) {
1038         // place the final section at the initial position
1039         Param.Append(V1);
1040         WSeq.Append(WSeq(ifin));
1041       }
1042       else {
1043         // it is necessary to find a medium section to impose by V1 and by V2
1044         Standard_Real pmin = RealLast(), pmax = RealFirst();
1045         TopoDS_Wire Wmin, Wmax;
1046         for (iseq = 1; iseq <= WSeq.Length(); iseq++) {
1047           if (Param.Value(iseq)<pmin) {
1048             pmin = Param.Value(iseq);
1049             Wmin = TopoDS::Wire(WSeq.Value(iseq));
1050           }
1051           if (Param.Value(iseq)>pmax) {
1052             pmax = Param.Value(iseq);
1053             Wmax = TopoDS::Wire(WSeq.Value(iseq));
1054           }
1055         }
1056         // medium section between Wmin and Wmax
1057         TopoDS_Wire Wres;
1058         Standard_Real dmin = Abs(pmin-V1);
1059         Standard_Real dmax = Abs(pmax-V2);
1060         if (ComputeSection(Wmin,Wmax,dmin,dmax,Wres)) {
1061           // impose section Wres at the beginning and the end
1062           Param.Append(V1);
1063           WSeq.Append(Wres);
1064           IndSec.Append(WSeq.Length());
1065           Param.Append(V2);
1066           WSeq.Append(Wres);
1067           IndSec.Append(WSeq.Length());
1068         }
1069       }
1070     }
1071     
1072     // parse sections by increasing parameter
1073     Standard_Boolean play_again = Standard_True;
1074     while (play_again) {
1075       play_again = Standard_False;
1076       for (iseq=1;iseq<=WSeq.Length();iseq++) {
1077         for (Standard_Integer jseq=iseq+1;jseq<=WSeq.Length();jseq++) {
1078           if (Param.Value(iseq) > Param.Value(jseq)) {
1079             Param.Exchange(iseq,jseq);
1080             WSeq.Exchange(iseq,jseq);
1081             IndSec.Exchange(iseq,jseq);
1082             play_again = Standard_True;
1083           }
1084         }
1085       }
1086     }
1087     //Fill the array of real indices of sections
1088     for (Standard_Integer ii = 1; ii <= mySeq.Length(); ii++)
1089       for (Standard_Integer jj = 1; jj <= IndSec.Length(); jj++)
1090         if (IndSec(jj) == ii)
1091         {
1092           myIndOfSec.Append(jj);
1093           break;
1094         }
1095     
1096 #ifdef DRAW
1097     if ( Affich) {
1098       char*  name = new char[100];
1099       Standard_Integer NBSECT = 0;
1100       for (Standard_Integer i=1;i<=WSeq.Length();i++) {
1101         NBSECT++;
1102         sprintf(name,"WSeq_%d",NBSECT);
1103         DBRep::Set(name,TopoDS::Wire(WSeq.Value(i)));
1104       }
1105     }
1106 #endif
1107     
1108     
1109     
1110     //  Calculate work sections 
1111     TopTools_SequenceOfShape WorkingSections;
1112     WorkingSections.Clear();
1113     TopTools_DataMapOfShapeListOfShape WorkingMap;
1114     BRepFill_CompatibleWires Georges(WSeq);
1115     Georges.SetPercent(0.1);
1116     Georges.Perform(Standard_False);
1117     if (Georges.IsDone()) {
1118       WorkingSections = Georges.Shape();
1119       WorkingMap = Georges.Generated();
1120       //For each sub-edge of each section
1121       //we save its splits
1122       for (Standard_Integer ii = 1; ii <= WSeq.Length(); ii++)
1123       {
1124         TopExp_Explorer Explo(WSeq(ii), TopAbs_EDGE);
1125         for (; Explo.More(); Explo.Next())
1126         {
1127           const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
1128           TopTools_ListOfShape aNewEdges = Georges.GeneratedShapes(anEdge);
1129           myEdgeNewEdges.Bind(anEdge, aNewEdges);
1130         }
1131       }
1132     }
1133     else {
1134       throw Standard_ConstructionError("PipeShell : uncompatible wires");
1135     }
1136     mySection = new (BRepFill_NSections) (WorkingSections,Transformations,Param,V1,V2);
1137     
1138   }// else
1139
1140   //  modify the law of location if contact
1141   if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1142       || (myTrihedron == GeomFill_IsGuideACWithContact) )  {
1143     Standard_Real fs, f, l, Delta, Length;
1144     Handle(GeomFill_LocationGuide) Loc;
1145     Handle(GeomFill_SectionLaw) Sec = mySection->ConcatenedLaw();
1146     myLocation->CurvilinearBounds(myLocation->NbLaw(), f, Length);
1147     Sec->GetDomain(fs,l);
1148     Delta = (l-fs)/Length;
1149
1150     Standard_Real angle, old_angle = 0;
1151     for (Standard_Integer ipath=1; ipath<=myLocation->NbLaw(); ipath++) {
1152       myLocation->CurvilinearBounds(ipath, f, l);
1153       Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(ipath));
1154       Loc->Set(Sec, Standard_True, fs + f*Delta, fs + l*Delta,
1155                old_angle, angle); // force the rotation 
1156       old_angle = angle;
1157     }      
1158   }
1159
1160   myStatus = myLocation->GetStatus();
1161   if (!mySection->IsDone())
1162     myStatus = GeomFill_PipeNotOk;
1163 }
1164
1165 //=======================================================================
1166 //function : Place
1167 //purpose  : Implement a Section in the local refernce frame
1168 //           and return its parameter on the trajectory
1169 //=======================================================================
1170 void BRepFill_PipeShell::Place(const BRepFill_Section& Sec,
1171                                TopoDS_Wire& W,
1172                                gp_Trsf& aTrsf,
1173                                Standard_Real& param)
1174 {
1175   BRepFill_SectionPlacement Place(myLocation, 
1176                                   Sec.Wire(),
1177                                   Sec.Vertex(),
1178                                   Sec.WithContact(),
1179                                   Sec.WithCorrection());
1180   TopoDS_Wire TmpWire =  Sec.Wire();
1181   aTrsf = Place.Transformation();
1182   //Transform the copy
1183   W = TopoDS::Wire(BRepBuilderAPI_Transform(TmpWire, aTrsf, Standard_True));
1184   ////////////////////////////////////
1185   param = Place.AbscissaOnPath();
1186 }
1187
1188
1189 //=======================================================================
1190 //function : ResetLoc
1191 //purpose  : Remove references to the sections in the laws of location
1192 //=======================================================================
1193  void BRepFill_PipeShell::ResetLoc() 
1194 {
1195   if ( (myTrihedron == GeomFill_IsGuidePlanWithContact)
1196       || (myTrihedron == GeomFill_IsGuideACWithContact) ) {
1197     Handle(GeomFill_LocationGuide) Loc;
1198     for (Standard_Integer isec=1; isec<=myLocation->NbLaw(); isec++) { 
1199       Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(isec));
1200       Loc->EraseRotation();// remove the rotation       
1201     }    
1202   }
1203 }
1204
1205 //=======================================================================
1206 //function : BuildHistory
1207 //purpose  : Builds history for edges and vertices of sections,
1208 //           for edges and vertices of spine
1209 //=======================================================================
1210 void BRepFill_PipeShell::BuildHistory(const BRepFill_Sweep& theSweep) 
1211 {
1212   //Filling of <myGenMap>
1213   const Handle(TopTools_HArray2OfShape)& anUEdges = theSweep.InterFaces();
1214   BRep_Builder BB;
1215   
1216   TopTools_DataMapOfIntegerShape IndWireMap;
1217   
1218   Standard_Integer indw, inde;
1219   TopoDS_Iterator itw;
1220   for (indw = 1; indw <= mySeq.Length(); indw++)
1221   {
1222     const TopoDS_Shape& Section = mySeq(indw).OriginalShape();
1223     TopoDS_Wire aSection;
1224     Standard_Boolean IsPunctual = mySeq(indw).IsPunctual();
1225     if (IsPunctual)
1226     {
1227       //for punctual sections (first or last)
1228       //we take all the wires generated along the path
1229       
1230       TopTools_ListOfShape* Elist = myGenMap.Bound(Section, TopTools_ListOfShape());
1231       for (Standard_Integer i = 1; i <= anUEdges->UpperRow(); i++)
1232         for (Standard_Integer j = 1; j <= anUEdges->UpperCol(); j++)
1233           Elist->Append(anUEdges->Value(i,j));
1234
1235       continue;
1236     }
1237     else
1238       aSection = TopoDS::Wire(Section);
1239     //Take the real index of section on the path
1240     Standard_Integer IndOfW = myIndOfSec(indw);
1241     const TopoDS_Wire& theWire = TopoDS::Wire(WSeq(IndOfW));
1242     BRepTools_WireExplorer wexp_sec(aSection);
1243     for (inde = 1; wexp_sec.More(); wexp_sec.Next())
1244     {
1245       const TopoDS_Edge& anOriginalEdge = TopoDS::Edge(wexp_sec.Current());
1246       TopoDS_Edge anEdge = TopoDS::Edge(mySeq(indw).ModifiedShape(anOriginalEdge));
1247       if (BRep_Tool::Degenerated(anEdge))
1248         continue;
1249
1250       TopoDS_Shell aShell;
1251       BB.MakeShell(aShell);
1252       TopoDS_Vertex aVertex [2];
1253       TopExp::Vertices(anOriginalEdge, aVertex[0], aVertex[1]);
1254       Standard_Integer SignOfAnEdge =
1255         (anOriginalEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
1256       
1257       //For each non-degenerated inde-th edge of <aSection>
1258       //we find inde-th edge in <theWire>
1259       TopoDS_Edge theEdge;
1260       BRepTools_WireExplorer wexp(theWire);
1261       for (Standard_Integer i = 1; wexp.More(); wexp.Next())
1262       {
1263         theEdge = TopoDS::Edge(wexp.Current());
1264         if (BRep_Tool::Degenerated(anEdge))
1265           continue;
1266         if (i == inde)
1267           break;
1268         i++;
1269       }
1270
1271       //Take the list of splits for <theEdge>
1272       const TopTools_ListOfShape& NewEdges = myEdgeNewEdges(theEdge);
1273       Standard_Integer SignOfANewEdge = 0, SignOfIndex = 0;
1274       TopTools_ListIteratorOfListOfShape iter(NewEdges);
1275       for (; iter.More(); iter.Next())
1276       {
1277         const TopoDS_Edge& aNewEdge = TopoDS::Edge(iter.Value());
1278         SignOfANewEdge = (aNewEdge.Orientation() == TopAbs_FORWARD)? 1 : -1;
1279         Standard_Integer anIndE = mySection->IndexOfEdge(aNewEdge);
1280         SignOfIndex = (anIndE > 0)? 1 : -1;
1281         anIndE = Abs(anIndE);
1282         //For an edge generated shape is a "tape" -
1283         //a shell usually containing this edge and
1284         //passing from beginning of path to its end
1285         TopoDS_Shape aTape = theSweep.Tape(anIndE);
1286         TopoDS_Iterator itsh(aTape);
1287         for (; itsh.More(); itsh.Next())
1288           BB.Add(aShell, itsh.Value());
1289       }
1290
1291       //Processing of vertices of <anEdge>
1292       //We should choose right index in <anUEdges>
1293       //for each vertex of edge 
1294       Standard_Integer ToReverse = SignOfAnEdge * SignOfANewEdge * SignOfIndex;
1295       Standard_Integer UIndex [2];
1296       UIndex[0] = Abs(mySection->IndexOfEdge(NewEdges.First()));
1297       UIndex[1] = Abs(mySection->IndexOfEdge(NewEdges.Last())) + ToReverse;
1298       if (ToReverse == -1)
1299       {
1300         UIndex[0]++;
1301         UIndex[1]++;
1302       }
1303       if (mySection->IsUClosed())
1304       {
1305         if (UIndex[0] > mySection->NbLaw())
1306           UIndex[0] = 1;
1307         if (UIndex[1] > mySection->NbLaw())
1308           UIndex[1] = 1;
1309       }
1310       //if (SignOfAnEdge * SignOfANewEdge == -1)
1311       if (SignOfAnEdge   == -1 ||
1312           SignOfANewEdge == -1)
1313       { Standard_Integer Tmp = UIndex[0]; UIndex[0] = UIndex[1]; UIndex[1] = Tmp; }
1314
1315       TopTools_IndexedDataMapOfShapeListOfShape VEmap;
1316       TopExp::MapShapesAndAncestors(aShell, TopAbs_VERTEX, TopAbs_EDGE, VEmap);
1317       for (Standard_Integer kk = 0; kk < 2; kk++)
1318       {
1319         if (myGenMap.IsBound(aVertex[kk]))
1320           continue;
1321         if (IndWireMap.IsBound(UIndex[kk]))
1322         {
1323           TopTools_ListOfShape* Elist = myGenMap.Bound(aVertex[kk], TopTools_ListOfShape());
1324           
1325           for (itw.Initialize( IndWireMap(UIndex[kk]) ); itw.More(); itw.Next())
1326             Elist->Append(itw.Value());
1327           
1328           continue;
1329         }
1330         
1331         //Collect u-edges
1332         TopTools_SequenceOfShape SeqEdges;
1333         Standard_Integer jj;
1334         for (jj = 1; jj <= anUEdges->UpperCol(); jj++)
1335           SeqEdges.Append(anUEdges->Value(UIndex[kk], jj));
1336
1337         //Assemble the wire ("rail" along the path)
1338         //checking for possible holes
1339         //(they appear with option "Round Corner")
1340         //and filling them
1341         //Missed edges are taken from <aShell>
1342         TopoDS_Wire aWire;
1343         BB.MakeWire(aWire);
1344         const TopoDS_Edge& FirstEdge = TopoDS::Edge(SeqEdges(1));
1345         if (FirstEdge.IsNull())
1346           continue;
1347         BB.Add(aWire, FirstEdge);
1348         TopoDS_Vertex FirstVertex, CurVertex;
1349         TopExp::Vertices(FirstEdge, FirstVertex, CurVertex);
1350         TopoDS_Edge CurEdge;
1351         for (jj = 2; jj <= SeqEdges.Length(); jj++)
1352         {
1353           CurEdge = TopoDS::Edge(SeqEdges(jj));
1354           TopoDS_Vertex Vfirst, Vlast;
1355           TopExp::Vertices(CurEdge, Vfirst, Vlast);
1356           if (CurVertex.IsSame(Vfirst))
1357             CurVertex = Vlast;
1358           else //a hole
1359           {
1360             const TopTools_ListOfShape& Elist = VEmap.FindFromKey(Vfirst);
1361             TopTools_ListIteratorOfListOfShape itl(Elist);
1362             for (; itl.More(); itl.Next())
1363             {
1364               const TopoDS_Edge& Candidate = TopoDS::Edge(itl.Value());
1365               if (Candidate.IsSame(CurEdge))
1366                 continue;
1367               TopoDS_Vertex V1, V2;
1368               TopExp::Vertices(Candidate, V1, V2);
1369               if (V1.IsSame(CurVertex) || V2.IsSame(CurVertex))
1370               {
1371                 BB.Add(aWire, Candidate);
1372                 break;
1373               }
1374             }
1375           }
1376           CurVertex = Vlast;
1377           BB.Add(aWire, CurEdge);
1378         } //for (jj = 2; jj <= SeqEdges.Length(); jj++)
1379         //case of closed wire
1380         if (myLocation->IsClosed() &&
1381             !CurVertex.IsSame(FirstVertex))
1382         {
1383           const TopTools_ListOfShape& Elist = VEmap.FindFromKey(CurVertex);
1384           TopTools_ListIteratorOfListOfShape itl(Elist);
1385           for (; itl.More(); itl.Next())
1386           {
1387             const TopoDS_Edge& Candidate = TopoDS::Edge(itl.Value());
1388             if (Candidate.IsSame(CurEdge))
1389               continue;
1390             TopoDS_Vertex V1, V2;
1391             TopExp::Vertices(Candidate, V1, V2);
1392             if (V1.IsSame(FirstVertex) || V2.IsSame(FirstVertex))
1393             {
1394               BB.Add(aWire, Candidate);
1395               break;
1396             }
1397           }
1398         }
1399
1400         TopTools_ListOfShape* Elist = myGenMap.Bound(aVertex[kk], TopTools_ListOfShape());
1401
1402         for (itw.Initialize(aWire); itw.More(); itw.Next())
1403           Elist->Append(itw.Value());
1404         
1405         //Save already built wire with its index
1406         IndWireMap.Bind(UIndex[kk], aWire);
1407       } //for (Standard_Integer kk = 0; kk < 2; kk++)
1408       ////////////////////////////////////
1409       
1410       TopTools_ListOfShape* Flist = myGenMap.Bound(anOriginalEdge, TopTools_ListOfShape());
1411       TopoDS_Iterator itsh(aShell);
1412       for (; itsh.More(); itsh.Next())
1413         Flist->Append(itsh.Value());
1414       ////////////////////////
1415
1416       inde++;
1417     }
1418   }
1419
1420   //For subshapes of spine
1421   const Handle(TopTools_HArray2OfShape)& aFaces  = theSweep.SubShape();
1422   const Handle(TopTools_HArray2OfShape)& aVEdges = theSweep.Sections();
1423   
1424   BRepTools_WireExplorer wexp(mySpine);
1425   inde = 0;
1426   Standard_Boolean ToExit = Standard_False;
1427   for (;;)
1428   {
1429     if (!wexp.More())
1430       ToExit = Standard_True;
1431     
1432     inde++;
1433
1434     if (!ToExit)
1435     {
1436       const TopoDS_Edge& anEdgeOfSpine = wexp.Current();
1437       
1438       TopTools_ListOfShape* Flist = myGenMap.Bound(anEdgeOfSpine, TopTools_ListOfShape());
1439       
1440       for (Standard_Integer i = 1; i <= aFaces->UpperRow(); i++)
1441       {
1442         const TopoDS_Shape& aFace = aFaces->Value(i, inde);
1443         if (aFace.ShapeType() == TopAbs_FACE)
1444           Flist->Append(aFace);
1445       }
1446     }
1447     
1448     const TopoDS_Vertex& aVertexOfSpine = wexp.CurrentVertex();
1449     TopTools_ListOfShape* ListVshapes = myGenMap.Bound(aVertexOfSpine, TopTools_ListOfShape());
1450     for (Standard_Integer i = 1; i <= aVEdges->UpperRow(); i++)
1451     {
1452       const TopoDS_Shape& aVshape = aVEdges->Value(i, inde);
1453       if (aVshape.ShapeType() == TopAbs_EDGE ||
1454           aVshape.ShapeType() == TopAbs_FACE)
1455         ListVshapes->Append(aVshape);
1456       else
1457       {
1458         TopoDS_Iterator itvshape(aVshape);
1459         for (; itvshape.More(); itvshape.Next())
1460         {
1461           const TopoDS_Shape& aSubshape = itvshape.Value();
1462           if (aSubshape.ShapeType() == TopAbs_EDGE ||
1463               aSubshape.ShapeType() == TopAbs_FACE)
1464             ListVshapes->Append(aSubshape);
1465           else
1466           {
1467             //it is wire
1468             for (itw.Initialize(aSubshape); itw.More(); itw.Next())
1469               ListVshapes->Append(itw.Value());
1470           }
1471         }
1472       }
1473     }
1474
1475     if (ToExit)
1476       break;
1477
1478     if (wexp.More())
1479       wexp.Next();
1480   }
1481 }
1482
1483
1484 // ---------------------------------------------------------------------------------
1485 // static function: BuildBoundaries
1486 // purpose:
1487 // ---------------------------------------------------------------------------------
1488 Standard_Boolean BuildBoundaries(const BRepFill_Sweep&               theSweep,
1489                                  const Handle(BRepFill_SectionLaw)&  theSection,
1490                                  TopoDS_Shape&                       theBottom,
1491                                  TopoDS_Shape&                       theTop) {
1492   
1493   TopoDS_Wire aBottomWire;
1494   TopoDS_Wire aTopWire;
1495   BRep_Builder aB;
1496   aB.MakeWire(aBottomWire);
1497   aB.MakeWire(aTopWire);
1498   Standard_Boolean bfoundbottom = Standard_False;
1499   Standard_Boolean bfoundtop = Standard_False;
1500   Handle(TopTools_HArray2OfShape) aVEdges = theSweep.Sections();
1501   Standard_Integer i = 0;
1502   Standard_Boolean bAllSame = Standard_True;
1503
1504   for(i = 1; i <= theSection->NbLaw(); i++) {
1505     const TopoDS_Shape& aBottomEdge = aVEdges->Value(i, aVEdges->LowerCol());
1506
1507     if(!aBottomEdge.IsNull() && (aBottomEdge.ShapeType() == TopAbs_EDGE)) {
1508       aB.Add(aBottomWire, aBottomEdge);
1509       bfoundbottom = Standard_True;
1510     }
1511     const TopoDS_Shape& aTopEdge = aVEdges->Value(i, aVEdges->UpperCol());
1512
1513     if(!aTopEdge.IsNull() && (aTopEdge.ShapeType() == TopAbs_EDGE)) {
1514       aB.Add(aTopWire, aTopEdge);
1515       bfoundtop = Standard_True;
1516     }
1517
1518     if(!aBottomEdge.IsNull() && !aTopEdge.IsNull() && !aBottomEdge.IsSame(aTopEdge))
1519       bAllSame = Standard_False;
1520   }
1521
1522   if(theSection->IsUClosed()) {
1523     aBottomWire.Closed(Standard_True);
1524     aTopWire.Closed(Standard_True);
1525   }
1526
1527   if(bfoundbottom) {
1528     theBottom = aBottomWire;
1529   }
1530
1531   if(bfoundtop) {
1532     theTop  = aTopWire;
1533   }
1534
1535   if(bAllSame && bfoundbottom && bfoundtop)
1536     theTop = theBottom;
1537
1538   return bfoundbottom || bfoundtop;
1539 }