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