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