Warnings on vc14 were eliminated
[occt.git] / src / BRepFill / BRepFill_Pipe.cxx
1 // Created on: 1994-06-07
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1994-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 <Adaptor3d_CurveOnSurface.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepBuilderAPI_Copy.hxx>
22 #include <BRepBuilderAPI_Transform.hxx>
23 #include <BRepClass3d_SolidClassifier.hxx>
24 #include <BRepFill_Edge3DLaw.hxx>
25 #include <BRepFill_LocationLaw.hxx>
26 #include <BRepFill_Pipe.hxx>
27 #include <BRepFill_SectionPlacement.hxx>
28 #include <BRepFill_ShapeLaw.hxx>
29 #include <BRepFill_Sweep.hxx>
30 #include <BRepLib.hxx>
31 #include <BRepLib_MakeVertex.hxx>
32 #include <BRepTools_Substitution.hxx>
33 #include <Geom2dAdaptor_HCurve.hxx>
34 #include <Geom_BSplineCurve.hxx>
35 #include <Geom_OffsetCurve.hxx>
36 #include <Geom_TrimmedCurve.hxx>
37 #include <GeomAbs_Shape.hxx>
38 #include <GeomAdaptor_HSurface.hxx>
39 #include <GeomFill_CorrectedFrenet.hxx>
40 #include <GeomFill_CurveAndTrihedron.hxx>
41 #include <GeomFill_DiscreteTrihedron.hxx>
42 #include <GeomFill_Frenet.hxx>
43 #include <gp_Pnt.hxx>
44 #include <Precision.hxx>
45 #include <ShapeUpgrade_RemoveLocations.hxx>
46 #include <Standard_DomainError.hxx>
47 #include <Standard_ErrorHandler.hxx>
48 #include <Standard_NotImplemented.hxx>
49 #include <StdFail_NotDone.hxx>
50 #include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
51 #include <TColStd_DataMapOfIntegerInteger.hxx>
52 #include <TopAbs_ShapeEnum.hxx>
53 #include <TopExp.hxx>
54 #include <TopoDS.hxx>
55 #include <TopoDS_Compound.hxx>
56 #include <TopoDS_Edge.hxx>
57 #include <TopoDS_Face.hxx>
58 #include <TopoDS_Iterator.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Shell.hxx>
61 #include <TopoDS_Solid.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <TopoDS_Wire.hxx>
64 #include <TopTools_DataMapOfShapeInteger.hxx>
65 #include <TopTools_ListIteratorOfListOfShape.hxx>
66 #include <TopTools_SequenceOfShape.hxx>
67
68 #ifdef DRAW
69 #include <DBRep.hxx>
70 static Standard_Boolean Affich = 0;
71 #endif
72
73 // ---------------------------------------------------------------------------------
74 // static function: UpdateMap
75 // purpose:
76 // ---------------------------------------------------------------------------------
77 static Standard_Boolean UpdateMap(const TopoDS_Shape&                 theKey,
78                                   const TopoDS_Shape&                 theValue,
79                                   TopTools_DataMapOfShapeListOfShape& theMap)
80 {
81   if(!theMap.IsBound(theKey))
82   {
83     TopTools_ListOfShape thelist;
84     theMap.Bind(theKey, thelist);
85   }
86   TopTools_ListOfShape& aList = theMap.ChangeFind(theKey);
87   TopTools_ListIteratorOfListOfShape anIt(aList);
88   Standard_Boolean found = Standard_False;
89
90   for(; anIt.More(); anIt.Next())
91   {
92     if(theValue.IsSame(anIt.Value()))
93     {
94       found = Standard_True;
95       break;
96     }
97   }
98
99   if(!found)
100     aList.Append(theValue);
101   
102   return !found;
103 }
104
105 static void ReverseModifiedEdges(TopoDS_Shape& aShape,
106                                  TopTools_MapOfShape& Emap)
107 {
108   TopExp_Explorer Explo(aShape, TopAbs_FACE);
109   BRep_Builder BB;
110   
111   for (; Explo.More(); Explo.Next())
112   {
113     TopoDS_Shape aFace = Explo.Current();
114     TopoDS_Iterator itf(aFace);
115     for (; itf.More(); itf.Next())
116     {
117       TopoDS_Shape aWire = itf.Value();
118       TopTools_ListOfShape Ledges;
119       TopoDS_Iterator itw(aWire);
120       for (; itw.More(); itw.Next())
121         Ledges.Append(itw.Value());
122
123       aWire.Free(Standard_True);
124       TopTools_ListIteratorOfListOfShape itl(Ledges);
125       for (; itl.More(); itl.Next())
126         BB.Remove(aWire, itl.Value());
127         
128       for (itl.Initialize(Ledges); itl.More(); itl.Next())
129       {
130         TopoDS_Shape anEdge = itl.Value();
131         if (Emap.Contains(anEdge))
132           anEdge.Reverse();
133         BB.Add(aWire, anEdge);
134       }
135     }
136   }
137 }
138
139 static void UpdateTolFromTopOrBottomPCurve(const TopoDS_Face& aFace,
140                                            TopoDS_Edge& anEdge)
141 {
142   Standard_Real fpar, lpar;
143   Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, aFace, fpar, lpar);
144   if (aPCurve.IsNull())
145     return;
146
147   Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar);
148   if (aCurve.IsNull())
149     return;
150
151   Handle(Geom2dAdaptor_HCurve) GAHC2d = new Geom2dAdaptor_HCurve(aPCurve, fpar, lpar);
152   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
153   Handle(GeomAdaptor_HSurface) GAHS = new GeomAdaptor_HSurface(aSurf);
154   Adaptor3d_CurveOnSurface ConS(GAHC2d, GAHS);
155
156   Standard_Real Tol = BRep_Tool::Tolerance(anEdge);
157   Standard_Real InitTol = Tol;
158   Standard_Real TolTol = Tol*Tol;
159   const Standard_Integer NCONTROL = 22;
160   Standard_Real delta = (lpar - fpar)/NCONTROL;
161   for (Standard_Integer i = 0; i <= NCONTROL; i++)
162   {
163     Standard_Real par = fpar + i*delta;
164     gp_Pnt pnt = aCurve->Value(par);
165     gp_Pnt prj = ConS.Value(par);
166     Standard_Real sqdist = pnt.SquareDistance(prj);
167     if (sqdist > TolTol)
168       TolTol = sqdist;
169   }
170   Tol = 1.00005 * Sqrt(TolTol);
171   if (Tol >= InitTol)
172   {
173     BRep_Builder BB;
174     BB.UpdateEdge(anEdge, Tol);
175     TopoDS_Iterator itv(anEdge);
176     for (; itv.More(); itv.Next())
177     {
178       TopoDS_Vertex aVertex = TopoDS::Vertex(itv.Value());
179       BB.UpdateVertex(aVertex, Tol);
180     }
181   }
182 }
183
184 //=======================================================================
185 //function : BRepFill_Pipe
186 //purpose  : 
187 //=======================================================================
188
189 BRepFill_Pipe::BRepFill_Pipe()
190 {
191   myDegmax = 11;
192   mySegmax = 100;
193   myContinuity = GeomAbs_C2;
194   myMode = GeomFill_IsCorrectedFrenet;
195   myForceApproxC1 = Standard_False;
196
197   myCurIndexOfSectionEdge = 1;
198 }
199
200
201 //=======================================================================
202 //function : BRepFill_Pipe
203 //purpose  : 
204 //=======================================================================
205
206 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire&  Spine,
207                              const TopoDS_Shape& Profile,
208                              const GeomFill_Trihedron aMode,
209                              const Standard_Boolean ForceApproxC1,
210                              const Standard_Boolean KPart)
211                              
212 {
213   myDegmax = 11;
214   mySegmax = 100;
215   
216   myMode = GeomFill_IsCorrectedFrenet;
217   if (aMode == GeomFill_IsFrenet ||
218       aMode == GeomFill_IsCorrectedFrenet ||
219       aMode == GeomFill_IsDiscreteTrihedron)
220     myMode = aMode;
221
222   myContinuity = GeomAbs_C2;
223   if (myMode == GeomFill_IsDiscreteTrihedron)
224     myContinuity = GeomAbs_C0;
225   
226   myForceApproxC1 = ForceApproxC1;
227
228   myCurIndexOfSectionEdge = 1;
229   
230   Perform(Spine, Profile, KPart);
231 }
232
233
234 //=======================================================================
235 //function : Perform
236 //purpose  : 
237 //=======================================================================
238
239 void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
240                             const TopoDS_Shape& Profile,
241                             const Standard_Boolean /*KPart*/)
242
243 {
244   mySections.Nullify();
245   myFaces.Nullify();
246   myEdges.Nullify();
247
248   mySpine   = Spine;
249   myProfile = Profile;
250
251   DefineRealSegmax();
252
253   BRepTools_WireExplorer wexp;
254   TopoDS_Shape TheProf; 
255
256   Handle(GeomFill_TrihedronLaw) TLaw;
257   switch (myMode)
258   {
259   case GeomFill_IsFrenet:
260     TLaw = new GeomFill_Frenet();
261     break;
262   case GeomFill_IsCorrectedFrenet:
263     TLaw = new GeomFill_CorrectedFrenet();
264     break;
265   case GeomFill_IsDiscreteTrihedron:
266     TLaw = new GeomFill_DiscreteTrihedron();
267     break;
268   default:
269     break;
270   }
271   Handle(GeomFill_CurveAndTrihedron) Loc = 
272     new (GeomFill_CurveAndTrihedron) (TLaw);
273   myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
274   if (myLoc->NbLaw() == 0) {
275     return; // Degenerated case
276   }
277   myLoc->TransformInG0Law(); // Set into continuity
278     
279   BRepFill_SectionPlacement Place(myLoc, Profile);
280   myTrsf = Place.Transformation();
281
282   TopLoc_Location Loc2(myTrsf), Loc1;
283   Loc1 = Profile.Location();
284   TopoDS_Shape aux;
285   TheProf =  myProfile;
286   TheProf.Location(Loc2.Multiplied(Loc1));
287  
288   // Construct First && Last Shape
289   Handle(GeomFill_LocationLaw) law;
290
291   gp_Mat M;
292   gp_Vec V;
293   gp_Trsf fila;
294   Standard_Real first, last;
295   myLoc->Law(1)->GetDomain(first, last);
296   myLoc->Law(1)->D0(first, M, V);
297     fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
298                    M(2,1), M(2,2), M(2,3), V.Y(),
299                    M(3,1), M(3,2), M(3,3), V.Z());
300
301   fila.Multiply(myTrsf);
302   TopLoc_Location LocFirst(fila);
303   myFirst = myProfile;
304   if ( ! LocFirst.IsIdentity()) {
305     //myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
306     myFirst = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
307   }
308
309   ShapeUpgrade_RemoveLocations RemLoc;
310   RemLoc.SetRemoveLevel(TopAbs_COMPOUND);
311   RemLoc.Remove(myFirst);
312   myFirst = RemLoc.GetResult();
313   
314   myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
315   myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
316 //    try { // Not good, but there are no other means to test SetValues
317   fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
318                  M(2,1), M(2,2), M(2,3), V.Y(),
319                  M(3,1), M(3,2), M(3,3), V.Z());
320   fila.Multiply(myTrsf);
321   TopLoc_Location LocLast(fila);
322   if (! myLoc->IsClosed() || LocFirst != LocLast) {
323     myLast = myProfile;
324     if ( ! LocLast.IsIdentity()) {
325       //myLast.Location(LocLast.Multiplied(myProfile.Location()) );
326       myLast = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
327     }
328   }
329   else {
330     myLast = myFirst;
331   }
332
333   RemLoc.Remove(myLast);
334   myLast = RemLoc.GetResult();
335   
336 #if DRAW
337   if (Affich) {
338     DBRep::Set("theprof",  TheProf);
339     DBRep::Set("thefirst", myFirst);
340     DBRep::Set("thelast" , myLast);
341  }
342 #endif
343  
344   myShape = MakeShape(TheProf, myFirst, myLast);
345 }
346
347
348 //=======================================================================
349 //function : Spine
350 //purpose  : 
351 //=======================================================================
352
353 const TopoDS_Shape& BRepFill_Pipe::Spine() const 
354 {
355   return mySpine;
356 }
357
358 //=======================================================================
359 //function : Profile
360 //purpose  : 
361 //=======================================================================
362
363 const TopoDS_Shape& BRepFill_Pipe::Profile() const 
364 {
365   return myProfile;
366 }
367
368 //=======================================================================
369 //function : Shape
370 //purpose  : 
371 //=======================================================================
372
373 const TopoDS_Shape& BRepFill_Pipe::Shape() const 
374 {
375   return myShape;
376 }
377
378 //=======================================================================
379 //function : ErrorOnSurface
380 //purpose  : 
381 //=======================================================================
382
383 Standard_Real BRepFill_Pipe::ErrorOnSurface() const 
384 {
385   return myErrorOnSurf;
386 }
387
388
389 //=======================================================================
390 //function : FirstShape
391 //purpose  : 
392 //=======================================================================
393
394 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const 
395 {
396   return myFirst;
397 }
398
399
400 //=======================================================================
401 //function : LastShape
402 //purpose  : 
403 //=======================================================================
404
405 const TopoDS_Shape& BRepFill_Pipe::LastShape() const 
406 {
407   return myLast;
408 }
409
410 //=======================================================================
411 //function : Generated
412 //purpose  : 
413 //=======================================================================
414 void BRepFill_Pipe::Generated(const TopoDS_Shape&   theShape,
415                               TopTools_ListOfShape& theList) 
416 {
417   theList.Clear();
418
419   if (theShape.IsSame(myProfile))
420     theList.Append(myShape);
421   else
422   {
423     if (theShape.ShapeType() == TopAbs_FACE ||
424         theShape.ShapeType() == TopAbs_WIRE)
425     {
426       if(myGenMap.IsBound(theShape))
427         theList = myGenMap.Find(theShape);
428     }
429     else if (theShape.ShapeType() == TopAbs_EDGE)
430     {
431       TopoDS_Iterator itw(mySpine);
432       for (; itw.More(); itw.Next())
433       {
434         const TopoDS_Edge& aSpineEdge = TopoDS::Edge(itw.Value());
435         const TopoDS_Shape& aFace = Face(aSpineEdge, TopoDS::Edge(theShape));
436         theList.Append(aFace);
437       }
438     }
439     else if (theShape.ShapeType() == TopAbs_VERTEX)
440     {
441       TopoDS_Iterator itw(mySpine);
442       for (; itw.More(); itw.Next())
443       {
444         const TopoDS_Edge& aSpineEdge = TopoDS::Edge(itw.Value());
445         const TopoDS_Shape& anEdge = Edge(aSpineEdge, TopoDS::Vertex(theShape));
446         theList.Append(anEdge);
447       }
448     }
449   }
450 }
451
452 //=======================================================================
453 //function : Face
454 //purpose  : 
455 //=======================================================================
456
457 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
458                                 const TopoDS_Edge& EProfile)
459 {
460   TopoDS_Face theFace;
461
462   if ( BRep_Tool::Degenerated(EProfile))
463     return theFace;
464
465   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
466
467   // *************************************************
468   // Search if EProfile is an edge of myProfile
469   // *************************************************
470   iprof = FindEdge(myProfile, EProfile, count);
471
472   if (!iprof) throw Standard_DomainError(
473               "BRepFill_Pipe::Face : Edge not in the Profile");
474
475
476   // *************************************************
477   // Search if ESpine  is an edge of mySpine and find 
478   // the index of the corresponding Filler
479   // *************************************************
480  for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
481     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
482
483   if (!ispin) throw Standard_DomainError(
484     "BRepFill_Pipe::Edge  : Edge not in the Spine");
485
486   theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
487   return theFace;
488
489 }
490
491 //=======================================================================
492 //function : Edge
493 //purpose  : 
494 //=======================================================================
495 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge&   ESpine,
496                                 const TopoDS_Vertex& VProfile)
497 {
498   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
499
500   // *************************************************
501   // Search if VProfile is a Vertex of myProfile
502   // *************************************************
503   iprof = FindVertex(myProfile, VProfile, count);
504   if (!iprof) throw Standard_DomainError(
505         "BRepFill_Pipe::Edge : Vertex not in the Profile");
506
507
508   // *************************************************
509   // Search if ESpine  is an edge of mySpine and find 
510   // the index of the corresponding Filler
511   // *************************************************
512    
513   for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
514     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
515
516   if (!ispin) throw Standard_DomainError(
517     "BRepFill_Pipe::Edge  : Edge not in the Spine");
518
519
520   // *************************************************
521   // Generate the corresponding Shape
522   // *************************************************  
523   TopoDS_Edge theEdge;
524   theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
525
526   return theEdge;
527
528 }
529
530
531 //=======================================================================
532 //function : Section
533 //purpose  : 
534 //=======================================================================
535
536 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const 
537 {
538   TopoDS_Iterator it, itv;
539
540   Standard_Integer ii, ispin = 0;
541
542   TopoDS_Shape curSect = myProfile;
543
544   // *************************************************
545   // Search if ESpine  is an edge of mySpine and find 
546   // the index of the corresponding Filler
547   // *************************************************
548
549   // iterate on all the edges of mySpine
550  for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++) 
551     if  (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
552
553   if (!ispin) throw Standard_DomainError(
554     "BRepFill_Pipe::Section  : Vertex not in the Spine");
555
556   BRep_Builder B;
557   TopoDS_Compound Comp; 
558   B.MakeCompound(Comp);
559   for (ii=1; ii<=mySections->ColLength(); ii++)
560     B.Add(Comp, mySections->Value(ii, ispin));
561   
562   return Comp;
563 }
564
565 //=======================================================================
566 //function : PipeLine
567 //purpose  : Construct a wire by sweeping of a point
568 //=======================================================================
569
570 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point)
571 {
572  // Postioning 
573  gp_Pnt P;
574  P = Point;
575  P.Transform(myTrsf);
576
577  BRepLib_MakeVertex MkV(P); 
578  Handle(BRepFill_ShapeLaw) Section = 
579         new (BRepFill_ShapeLaw) (MkV.Vertex());
580
581  // Sweeping
582  BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
583  MkSw.SetForceApproxC1(myForceApproxC1);
584  MkSw.Build( myReversedEdges, myTapes, myRails,
585              BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
586  TopoDS_Shape aLocalShape = MkSw.Shape();
587  myErrorOnSurf = MkSw.ErrorOnSurface();
588  return TopoDS::Wire(aLocalShape);
589 // return TopoDS::Wire(MkSw.Shape());
590 }
591
592 //=======================================================================
593 //function : MakeShape
594 //purpose  : 
595 //=======================================================================
596
597 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
598                                       const TopoDS_Shape& FirstShape,
599                                       const TopoDS_Shape& LastShape)
600 {
601   TopoDS_Shape result;
602   BRep_Builder B;
603   Standard_Boolean explode = Standard_False; 
604   TopoDS_Shape TheS, TheFirst, TheLast;
605   Standard_Integer InitialLength = 0;
606   TheS = S;
607   TheFirst = FirstShape;
608   TheLast = LastShape;
609   if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
610
611   // there are two kinds of generation
612   //  1. generate with S from each Filler (Vertex, Edge)
613   //  2. call MakeShape recursively on the subshapes of S
614   //
615   // explode is True in the second case
616
617   // create the result empty
618
619   switch (S.ShapeType()) {
620
621   case TopAbs_VERTEX :
622     {
623       B.MakeWire(TopoDS::Wire(result));
624       break;
625     }
626           
627   case TopAbs_EDGE :
628     {
629       TopoDS_Wire W;
630       B.MakeShell(TopoDS::Shell(result));
631       B.MakeWire(W);
632       B.Add(W, S);
633       W.Closed(BRep_Tool::IsClosed(S));
634       TheS = W;
635       if (!FirstShape.IsNull()) {
636         B.MakeWire(W);
637         B.Add(W, FirstShape);
638         W.Closed(BRep_Tool::IsClosed(FirstShape));
639         TheFirst = W;
640       }
641       if (!LastShape.IsNull()) {
642         B.MakeWire(W);
643         B.Add(W, LastShape);
644         W.Closed(BRep_Tool::IsClosed(LastShape));
645         TheLast = W;
646       }
647       result.Closed (BRep_Tool::IsClosed (result));
648       break;
649     }
650           
651   case TopAbs_WIRE :
652     B.MakeShell(TopoDS::Shell(result));
653     break;
654
655   case TopAbs_FACE :
656     {
657       B.MakeShell(TopoDS::Shell(result));
658       explode = Standard_True;
659       if ( !mySpine.Closed() && !TheFirst.IsNull()) {
660          B.Add(result, TheFirst.Reversed());
661       }
662       result.Closed (BRep_Tool::IsClosed (result));
663       break;
664     }
665
666   case TopAbs_SHELL :
667     {
668       B.MakeCompSolid(TopoDS::CompSolid(result));
669       explode = Standard_True;
670       break;
671     }
672
673   case TopAbs_SOLID :
674   case TopAbs_COMPSOLID :
675     throw Standard_DomainError("BRepFill_Pipe::profile contains solids");
676     break;
677
678   case TopAbs_COMPOUND :
679     {
680       B.MakeCompound(TopoDS::Compound(result));
681       explode = Standard_True;
682       break;
683     }
684   default:
685     break;
686   }
687
688   if (explode) {
689     // add the subshapes
690     TopoDS_Iterator itFirst, itLast;
691     TopoDS_Shape first, last;
692     if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
693     if (!TheLast.IsNull()) itLast.Initialize(TheLast);
694
695     for (TopoDS_Iterator it(S); it.More(); it.Next()) {
696       if (!TheFirst.IsNull()) first = itFirst.Value();
697       if (!TheLast.IsNull())  last = itLast.Value();
698       if (TheS.ShapeType() == TopAbs_FACE ) 
699         MakeShape(it.Value(), first, last);
700       else
701         B.Add(result,MakeShape(it.Value(), first, last));
702
703       if (!TheFirst.IsNull()) itFirst.Next();
704       if (!TheLast.IsNull())  itLast.Next();
705     }
706   }
707   
708   else {
709     if (TheS.ShapeType() == TopAbs_VERTEX ) {
710      Handle(BRepFill_ShapeLaw) Section = 
711         new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
712       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
713       MkSw.SetForceApproxC1(myForceApproxC1);
714       MkSw.Build( myReversedEdges, myTapes, myRails,
715                   BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
716       result = MkSw.Shape();
717       UpdateMap(TheS.Located(myProfile.Location()), result, myGenMap);
718       myErrorOnSurf = MkSw.ErrorOnSurface();
719
720       Handle(TopTools_HArray2OfShape) aSections = MkSw.Sections();
721
722       if (aSections.IsNull() == Standard_False) {
723         const Standard_Integer aVLast = aSections->UpperCol();
724
725         myFirst = aSections->Value(1, 1);
726         myLast  = aSections->Value(1, aVLast);
727       }
728     }
729
730     if (TheS.ShapeType() == TopAbs_WIRE ) {
731       Handle(BRepFill_ShapeLaw) Section = 
732         new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
733       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
734       MkSw.SetBounds(TopoDS::Wire(TheFirst), 
735                      TopoDS::Wire(TheLast));
736       MkSw.SetForceApproxC1(myForceApproxC1);
737       MkSw.Build( myReversedEdges, myTapes, myRails,
738                   BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
739       result = MkSw.Shape();
740       UpdateMap(TheS.Located(myProfile.Location()), result, myGenMap);
741       myErrorOnSurf = MkSw.ErrorOnSurface();
742       //Correct <myFirst> and <myLast>
743       ReverseModifiedEdges(myFirst, myReversedEdges);
744       ReverseModifiedEdges(myLast, myReversedEdges);
745
746       // Labeling of elements
747       if (mySections.IsNull()) {
748         myFaces    = MkSw.SubShape();
749         mySections = MkSw.Sections();
750         myEdges    = MkSw.InterFaces();
751       }
752       else {
753         Handle(TopTools_HArray2OfShape) Aux, Somme;
754         Standard_Integer length;
755         Standard_Integer ii, jj, kk;
756
757         Aux = MkSw.SubShape();
758         length = Aux->ColLength() + myFaces->ColLength(); 
759         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
760                                                Aux->RowLength());
761         for (jj=1; jj<=myFaces->RowLength(); jj++) {
762           for (ii=1; ii<=myFaces->ColLength(); ii++)
763             Somme->SetValue(ii, jj, myFaces->Value(ii, jj));
764  
765           for (kk=1, ii=myFaces->ColLength()+1; 
766                kk <=Aux->ColLength(); kk++, ii++)
767             Somme->SetValue(ii, jj, Aux->Value(kk, jj));
768         }
769         myFaces = Somme;    
770
771         Aux = MkSw.Sections();
772         length = Aux->ColLength() + mySections->ColLength(); 
773         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
774                                                Aux->RowLength());
775         for (jj=1; jj<=mySections->RowLength(); jj++) {
776           for (ii=1; ii<=mySections->ColLength(); ii++)
777             Somme->SetValue(ii, jj, mySections->Value(ii, jj));
778
779           myCurIndexOfSectionEdge = mySections->ColLength()+1;
780           
781           for (kk=1, ii=mySections->ColLength()+1; 
782                kk <=Aux->ColLength(); kk++, ii++)
783             Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
784         }
785         mySections = Somme;
786
787         Aux = MkSw.InterFaces();
788         length = Aux->ColLength() + myEdges->ColLength(); 
789         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
790                                                Aux->RowLength());
791         for (jj=1; jj<=myEdges->RowLength(); jj++) {
792           for (ii=1; ii<=myEdges->ColLength(); ii++)
793             Somme->SetValue(ii, jj, myEdges->Value(ii, jj));
794  
795           for (kk=1, ii=myEdges->ColLength()+1; 
796                kk <=Aux->ColLength(); kk++, ii++)
797             Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
798         }
799
800         myEdges = Somme;
801       }
802     }
803   }
804       
805   if ( TheS.ShapeType() == TopAbs_FACE ) {
806     Standard_Integer ii, jj;
807     //jgv
808     TopExp_Explorer Explo(result, TopAbs_FACE);
809     for (; Explo.More(); Explo.Next())
810     {
811       TopoDS_Shape aFace = Explo.Current();
812       RebuildTopOrBottomFace(aFace.Reversed(), Standard_True); //top face was reversed
813     }
814     /////
815     TopoDS_Face F;
816     for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
817       for (jj=1; jj<=myFaces->RowLength(); jj++) {
818         F = TopoDS::Face(myFaces->Value(ii, jj));
819         if (!F.IsNull()) B.Add(result, F);
820       }
821     }
822
823     if ( !mySpine.Closed()) {
824       // if Spine is not closed 
825       // add the last face of the solid
826
827       //jgv
828       RebuildTopOrBottomFace(TheLast, Standard_False); //bottom face
829       /////
830       B.Add(result, TopoDS::Face(TheLast));
831     }
832
833     TopoDS_Solid solid;
834     BRep_Builder BS;
835     BS.MakeSolid(solid);
836
837     result.Closed(Standard_True);
838     BS.Add(solid,TopoDS::Shell(result));
839
840     BRepClass3d_SolidClassifier SC(solid);
841     SC.PerformInfinitePoint(Precision::Confusion());
842     if ( SC.State() == TopAbs_IN) {
843       BS.MakeSolid(solid);
844       TopoDS_Shape aLocalShape = result.Reversed();
845       BS.Add(solid,TopoDS::Shell(aLocalShape));
846 //      BS.Add(solid,TopoDS::Shell(result.Reversed()));
847     }
848     UpdateMap(TheS.Located(myProfile.Location()), solid, myGenMap);
849     return solid;
850   }
851   else {
852     return result;
853   }
854 }
855
856 //============================================================================
857 //function : FindEdge
858 //purpose  : Find the number of edge corresponding to the edge of the profile.
859 //============================================================================
860
861 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
862                                          const TopoDS_Edge& E,
863                                          Standard_Integer& InitialLength) const
864 {
865   Standard_Integer result = 0;
866
867   switch (S.ShapeType()) {
868           
869   case TopAbs_EDGE :
870     {
871       InitialLength++;
872       if (S.IsSame(E)) result = InitialLength;
873       break;
874     }
875           
876   case TopAbs_WIRE :
877     {
878       Handle(BRepFill_ShapeLaw) Section = 
879         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
880       Standard_Integer NbLaw = Section->NbLaw();
881
882       for (Standard_Integer ii = 1; (ii<=NbLaw) && (!result); ii++) {
883         if (E.IsSame(Section->Edge(ii)) ) result = InitialLength + ii;
884       }
885       InitialLength += NbLaw;
886       break;
887     }
888
889   case TopAbs_FACE :
890   case TopAbs_SHELL :
891   case TopAbs_COMPOUND :
892     {
893      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
894        result = FindEdge(it.Value(), E, InitialLength );
895      break;
896     }
897
898   case TopAbs_SOLID :
899   case TopAbs_COMPSOLID :
900     throw Standard_DomainError("BRepFill_Pipe::SOLID or COMPSOLID");
901     break;
902   default:
903     break;
904   }
905
906   return result; 
907 }
908
909 //=======================================================================
910 //function : FindVertex
911 //purpose  : Find the number of edge corresponding to an edge of the profile.
912 //=======================================================================
913
914 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
915                                            const TopoDS_Vertex& V,
916                                            Standard_Integer& InitialLength) const
917 {
918   Standard_Integer result = 0;
919
920   switch (S.ShapeType()) {
921   case TopAbs_VERTEX :
922     {
923       InitialLength++;
924       if (S.IsSame(V)) result = InitialLength;
925       break;
926     }
927           
928   case TopAbs_EDGE :
929     {
930       TopoDS_Vertex VF, VL;
931       TopExp::Vertices(TopoDS::Edge(S), VF, VL);
932       if (S.Orientation() == TopAbs_REVERSED) {
933         TopoDS_Vertex aux;
934         aux = VF; VF = VL; VL = aux;
935       }
936       if (VF.IsSame(V)) result = InitialLength+1;
937       else if (VL.IsSame(V)) result = InitialLength+2;
938       InitialLength += 2;
939       break;
940     }
941           
942   case TopAbs_WIRE :
943     {
944       Standard_Integer ii = InitialLength+1;
945       Handle(BRepFill_ShapeLaw) Section = 
946         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
947       InitialLength += Section->NbLaw()+1;
948      
949       for (; (ii<=InitialLength) && (!result); ii++) {
950         if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
951       }
952       break;
953     }
954
955   case TopAbs_FACE :
956   case TopAbs_SHELL :
957   case TopAbs_COMPOUND :
958     {
959      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
960        result = FindVertex(it.Value(), V, InitialLength);
961      break;
962     }
963
964   case TopAbs_SOLID :
965   case TopAbs_COMPSOLID :
966     throw Standard_DomainError("BRepFill_Pipe::SOLID or COMPSOLID");
967     break;
968   default:
969     break;
970   }
971
972   return result; 
973 }
974
975 //=======================================================================
976 //function : DefineRealSegmax
977 //purpose  : Defines the real number of segments
978 //           required in the case of bspline spine
979 //=======================================================================
980
981 void BRepFill_Pipe::DefineRealSegmax()
982 {
983   Standard_Integer RealSegmax = 0;
984
985   TopoDS_Iterator iter(mySpine);
986   for (; iter.More(); iter.Next())
987     {
988       TopoDS_Edge E = TopoDS::Edge(iter.Value());
989       Standard_Real first, last;
990       Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
991       if (C.IsNull())
992         continue;
993       while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
994              C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
995         {
996           if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
997             C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
998           if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
999             C = Handle(Geom_OffsetCurve)::DownCast (C)->BasisCurve();
1000         }
1001       if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
1002         {
1003           Handle(Geom_BSplineCurve) BC (Handle(Geom_BSplineCurve)::DownCast (C));
1004           Standard_Integer NbKnots = BC->NbKnots();
1005           Standard_Integer RealNbKnots = NbKnots;
1006           if (first > BC->FirstParameter())
1007             {
1008               Standard_Integer I1, I2;
1009               BC->LocateU( first, Precision::PConfusion(), I1, I2 );
1010               RealNbKnots -= I1-1;
1011             }
1012           if (last < BC->LastParameter())
1013             {
1014               Standard_Integer I1, I2;
1015               BC->LocateU( last, Precision::PConfusion(), I1, I2 );
1016               RealNbKnots -= NbKnots-I2;
1017             }
1018           RealSegmax += RealNbKnots-1;
1019         }
1020     }
1021
1022   if (mySegmax < RealSegmax)
1023     mySegmax = RealSegmax;
1024 }
1025
1026 //=======================================================================
1027 //function : RebuildTopOrBottomFace
1028 //purpose  : Correct orientation of v-iso edges
1029 //           according to new 3d and 2d curves taken from swept surfaces
1030 //=======================================================================
1031
1032 void BRepFill_Pipe::RebuildTopOrBottomFace(const TopoDS_Shape& aFace,
1033                                            const Standard_Boolean IsTop) const
1034 {
1035   Standard_Integer IndexOfSection =
1036     (IsTop)? 1 : mySections->RowLength();
1037
1038   Standard_Integer ii;
1039   BRep_Builder BB;
1040   TopoDS_Iterator itf(aFace);
1041   for (; itf.More(); itf.Next())
1042   {
1043     TopoDS_Shape aWire = itf.Value();
1044     TopTools_SequenceOfShape InitEdges;
1045     TopTools_SequenceOfShape ResEdges;
1046     TopoDS_Iterator itw(aWire);
1047     for (; itw.More(); itw.Next())
1048     {
1049       TopoDS_Shape anEdge = itw.Value();
1050       for (ii = myCurIndexOfSectionEdge; ii <= mySections->ColLength(); ii++)
1051       {
1052         TopoDS_Shape aVisoEdge = mySections->Value(ii, IndexOfSection);
1053         if (anEdge.IsSame(aVisoEdge))
1054         {
1055           InitEdges.Append(anEdge);
1056           ResEdges.Append(aVisoEdge);
1057           break;
1058         }
1059       }
1060     }
1061     aWire.Free(Standard_True);
1062     for (ii = 1; ii <= InitEdges.Length(); ii++)
1063     {
1064       BB.Remove(aWire, InitEdges(ii));
1065       UpdateTolFromTopOrBottomPCurve(TopoDS::Face(aFace), TopoDS::Edge(ResEdges(ii)));
1066       BB.Add(aWire, ResEdges(ii));
1067     }
1068   }
1069 }