0032402: Coding Rules - eliminate msvc warning C4668 (symbol is not defined as a...
[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_Curve.hxx>
34 #include <Geom_BSplineCurve.hxx>
35 #include <Geom_OffsetCurve.hxx>
36 #include <Geom_TrimmedCurve.hxx>
37 #include <GeomAbs_Shape.hxx>
38 #include <GeomAdaptor_Surface.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_DataMapOfIntegerShape.hxx>
66 #include <TopTools_ListIteratorOfListOfShape.hxx>
67 #include <TopTools_SequenceOfShape.hxx>
68
69 #ifdef DRAW
70 #include <DBRep.hxx>
71 static Standard_Boolean Affich = 0;
72 #endif
73
74 // ---------------------------------------------------------------------------------
75 // static function: UpdateMap
76 // purpose:
77 // ---------------------------------------------------------------------------------
78 static Standard_Boolean UpdateMap(const TopoDS_Shape&                 theKey,
79                                   const TopoDS_Shape&                 theValue,
80                                   TopTools_DataMapOfShapeListOfShape& theMap)
81 {
82   if(!theMap.IsBound(theKey))
83   {
84     TopTools_ListOfShape thelist;
85     theMap.Bind(theKey, thelist);
86   }
87   TopTools_ListOfShape& aList = theMap.ChangeFind(theKey);
88   TopTools_ListIteratorOfListOfShape anIt(aList);
89   Standard_Boolean found = Standard_False;
90
91   for(; anIt.More(); anIt.Next())
92   {
93     if(theValue.IsSame(anIt.Value()))
94     {
95       found = Standard_True;
96       break;
97     }
98   }
99
100   if(!found)
101     aList.Append(theValue);
102   
103   return !found;
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_Curve) GAHC2d = new Geom2dAdaptor_Curve(aPCurve, fpar, lpar);
119   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
120   Handle(GeomAdaptor_Surface) GAHS = new GeomAdaptor_Surface(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
268   fila.Multiply(myTrsf);
269   TopLoc_Location LocFirst(fila);
270   myFirst = myProfile;
271   if ( ! LocFirst.IsIdentity()) {
272     //myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
273     myFirst = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
274   }
275
276   ShapeUpgrade_RemoveLocations RemLoc;
277   RemLoc.SetRemoveLevel(TopAbs_COMPOUND);
278   RemLoc.Remove(myFirst);
279   myFirst = RemLoc.GetResult();
280   
281   myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
282   myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
283 //    try { // Not good, but there are no other means to test SetValues
284   fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
285                  M(2,1), M(2,2), M(2,3), V.Y(),
286                  M(3,1), M(3,2), M(3,3), V.Z());
287   fila.Multiply(myTrsf);
288   TopLoc_Location LocLast(fila);
289   if (! myLoc->IsClosed() || LocFirst != LocLast) {
290     myLast = myProfile;
291     if ( ! LocLast.IsIdentity()) {
292       //myLast.Location(LocLast.Multiplied(myProfile.Location()) );
293       myLast = BRepBuilderAPI_Transform(myProfile, fila, Standard_True); //copy
294     }
295   }
296   else {
297     myLast = myFirst;
298   }
299
300   RemLoc.Remove(myLast);
301   myLast = RemLoc.GetResult();
302   
303 #ifdef DRAW
304   if (Affich) {
305     DBRep::Set("theprof",  TheProf);
306     DBRep::Set("thefirst", myFirst);
307     DBRep::Set("thelast" , myLast);
308  }
309 #endif
310  
311   myShape = MakeShape(TheProf, myProfile, myFirst, myLast);
312 }
313
314
315 //=======================================================================
316 //function : Spine
317 //purpose  : 
318 //=======================================================================
319
320 const TopoDS_Shape& BRepFill_Pipe::Spine() const 
321 {
322   return mySpine;
323 }
324
325 //=======================================================================
326 //function : Profile
327 //purpose  : 
328 //=======================================================================
329
330 const TopoDS_Shape& BRepFill_Pipe::Profile() const 
331 {
332   return myProfile;
333 }
334
335 //=======================================================================
336 //function : Shape
337 //purpose  : 
338 //=======================================================================
339
340 const TopoDS_Shape& BRepFill_Pipe::Shape() const 
341 {
342   return myShape;
343 }
344
345 //=======================================================================
346 //function : ErrorOnSurface
347 //purpose  : 
348 //=======================================================================
349
350 Standard_Real BRepFill_Pipe::ErrorOnSurface() const 
351 {
352   return myErrorOnSurf;
353 }
354
355
356 //=======================================================================
357 //function : FirstShape
358 //purpose  : 
359 //=======================================================================
360
361 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const 
362 {
363   return myFirst;
364 }
365
366
367 //=======================================================================
368 //function : LastShape
369 //purpose  : 
370 //=======================================================================
371
372 const TopoDS_Shape& BRepFill_Pipe::LastShape() const 
373 {
374   return myLast;
375 }
376
377 //=======================================================================
378 //function : Generated
379 //purpose  : 
380 //=======================================================================
381 void BRepFill_Pipe::Generated(const TopoDS_Shape&   theShape,
382                               TopTools_ListOfShape& theList) 
383 {
384   theList.Clear();
385
386   if(myGenMap.IsBound(theShape)) {
387     theList = myGenMap.Find(theShape);
388   }
389 }
390
391 //=======================================================================
392 //function : Face
393 //purpose  : 
394 //=======================================================================
395
396 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
397                                 const TopoDS_Edge& EProfile)
398 {
399   TopoDS_Face theFace;
400
401   if ( BRep_Tool::Degenerated(EProfile))
402     return theFace;
403
404   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
405
406   // *************************************************
407   // Search if EProfile is an edge of myProfile
408   // *************************************************
409   iprof = FindEdge(myProfile, EProfile, count);
410
411   if (!iprof) throw Standard_DomainError(
412               "BRepFill_Pipe::Face : Edge not in the Profile");
413
414
415   // *************************************************
416   // Search if ESpine  is an edge of mySpine and find 
417   // the index of the corresponding Filler
418   // *************************************************
419  for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
420     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
421
422   if (!ispin) throw Standard_DomainError(
423     "BRepFill_Pipe::Edge  : Edge not in the Spine");
424
425   theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
426   return theFace;
427
428 }
429
430 //=======================================================================
431 //function : Edge
432 //purpose  : 
433 //=======================================================================
434 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge&   ESpine,
435                                 const TopoDS_Vertex& VProfile)
436 {
437   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
438
439   // *************************************************
440   // Search if VProfile is a Vertex of myProfile
441   // *************************************************
442   iprof = FindVertex(myProfile, VProfile, count);
443   if (!iprof) throw Standard_DomainError(
444         "BRepFill_Pipe::Edge : Vertex not in the Profile");
445
446
447   // *************************************************
448   // Search if ESpine  is an edge of mySpine and find 
449   // the index of the corresponding Filler
450   // *************************************************
451    
452   for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
453     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
454
455   if (!ispin) throw Standard_DomainError(
456     "BRepFill_Pipe::Edge  : Edge not in the Spine");
457
458
459   // *************************************************
460   // Generate the corresponding Shape
461   // *************************************************  
462   TopoDS_Edge theEdge;
463   theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
464
465   return theEdge;
466
467 }
468
469
470 //=======================================================================
471 //function : Section
472 //purpose  : 
473 //=======================================================================
474
475 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const 
476 {
477   TopoDS_Iterator it, itv;
478
479   Standard_Integer ii, ispin = 0;
480
481   TopoDS_Shape curSect = myProfile;
482
483   // *************************************************
484   // Search if ESpine  is an edge of mySpine and find 
485   // the index of the corresponding Filler
486   // *************************************************
487
488   // iterate on all the edges of mySpine
489  for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++) 
490     if  (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
491
492   if (!ispin) throw Standard_DomainError(
493     "BRepFill_Pipe::Section  : Vertex not in the Spine");
494
495   BRep_Builder B;
496   TopoDS_Compound Comp; 
497   B.MakeCompound(Comp);
498   for (ii=1; ii<=mySections->ColLength(); ii++)
499     B.Add(Comp, mySections->Value(ii, ispin));
500   
501   return Comp;
502 }
503
504 //=======================================================================
505 //function : PipeLine
506 //purpose  : Construct a wire by sweeping of a point
507 //=======================================================================
508
509 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point)
510 {
511  // Postioning 
512  gp_Pnt P;
513  P = Point;
514  P.Transform(myTrsf);
515
516  TopoDS_Vertex VertexSection = BRepLib_MakeVertex(P); 
517  Handle(BRepFill_ShapeLaw) Section = 
518         new (BRepFill_ShapeLaw) (VertexSection);
519
520  // Sweeping
521  BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
522  MkSw.SetForceApproxC1(myForceApproxC1);
523  MkSw.Build( myReversedEdges, myTapes, myRails,
524              BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
525  TopoDS_Shape aLocalShape = MkSw.Shape();
526  myErrorOnSurf = MkSw.ErrorOnSurface();
527  BuildHistory(MkSw, VertexSection);
528  return TopoDS::Wire(aLocalShape);
529 // return TopoDS::Wire(MkSw.Shape());
530 }
531
532 //=======================================================================
533 //function : MakeShape
534 //purpose  : 
535 //=======================================================================
536
537 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
538                                       const TopoDS_Shape& theOriginalS,
539                                       const TopoDS_Shape& FirstShape,
540                                       const TopoDS_Shape& LastShape)
541 {
542   TopoDS_Shape result;
543   BRep_Builder B;
544   Standard_Boolean explode = Standard_False; 
545   TopoDS_Shape TheS, TheFirst, TheLast;
546   Standard_Integer InitialLength = 0;
547   TheS = S;
548   TheFirst = FirstShape;
549   TheLast = LastShape;
550   if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
551
552   TopLoc_Location BackLoc(myTrsf.Inverted());
553
554   // there are two kinds of generation
555   //  1. generate with S from each Filler (Vertex, Edge)
556   //  2. call MakeShape recursively on the subshapes of S
557   //
558   // explode is True in the second case
559
560   // create the result empty
561
562   switch (S.ShapeType()) {
563
564   case TopAbs_VERTEX :
565     {
566       B.MakeWire(TopoDS::Wire(result));
567       break;
568     }
569           
570   case TopAbs_EDGE :
571     {
572       TopoDS_Wire W;
573       B.MakeShell(TopoDS::Shell(result));
574       B.MakeWire(W);
575       B.Add(W, S);
576       W.Closed(BRep_Tool::IsClosed(S));
577       TheS = W;
578       if (!FirstShape.IsNull()) {
579         B.MakeWire(W);
580         B.Add(W, FirstShape);
581         W.Closed(BRep_Tool::IsClosed(FirstShape));
582         TheFirst = W;
583       }
584       if (!LastShape.IsNull()) {
585         B.MakeWire(W);
586         B.Add(W, LastShape);
587         W.Closed(BRep_Tool::IsClosed(LastShape));
588         TheLast = W;
589       }
590       result.Closed (BRep_Tool::IsClosed (result));
591       break;
592     }
593           
594   case TopAbs_WIRE :
595     B.MakeShell(TopoDS::Shell(result));
596     break;
597
598   case TopAbs_FACE :
599     {
600       B.MakeShell(TopoDS::Shell(result));
601       explode = Standard_True;
602       if ( !mySpine.Closed() && !TheFirst.IsNull()) {
603          B.Add(result, TheFirst.Reversed());
604       }
605       result.Closed (BRep_Tool::IsClosed (result));
606       break;
607     }
608
609   case TopAbs_SHELL :
610     {
611       B.MakeCompSolid(TopoDS::CompSolid(result));
612       explode = Standard_True;
613       break;
614     }
615
616   case TopAbs_SOLID :
617   case TopAbs_COMPSOLID :
618     throw Standard_DomainError("BRepFill_Pipe::profile contains solids");
619     break;
620
621   case TopAbs_COMPOUND :
622     {
623       B.MakeCompound(TopoDS::Compound(result));
624       explode = Standard_True;
625       break;
626     }
627   default:
628     break;
629   }
630
631   if (explode) {
632     // add the subshapes
633     TopoDS_Iterator itFirst, itLast;
634     TopoDS_Shape first, last;
635     if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
636     if (!TheLast.IsNull()) itLast.Initialize(TheLast);
637
638     TopoDS_Iterator it(S);
639     TopoDS_Iterator itorig(theOriginalS);
640     for (; it.More(); it.Next(),itorig.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(), itorig.Value(), first, last);
645       else
646         B.Add(result,MakeShape(it.Value(), itorig.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       UpdateMap(theOriginalS, result, myGenMap);
663       myErrorOnSurf = MkSw.ErrorOnSurface();
664
665       Handle(TopTools_HArray2OfShape) aSections = MkSw.Sections();
666
667       if (aSections.IsNull() == Standard_False) {
668         const Standard_Integer aVLast = aSections->UpperCol();
669
670         myFirst = aSections->Value(1, 1);
671         myLast  = aSections->Value(1, aVLast);
672       }
673
674       BuildHistory(MkSw, theOriginalS);
675     }
676
677     if (TheS.ShapeType() == TopAbs_WIRE ) {
678       Handle(BRepFill_ShapeLaw) Section = 
679         new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
680       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
681       MkSw.SetBounds(TopoDS::Wire(TheFirst), 
682                      TopoDS::Wire(TheLast));
683       MkSw.SetForceApproxC1(myForceApproxC1);
684       MkSw.Build( myReversedEdges, myTapes, myRails,
685                   BRepFill_Modified, myContinuity, GeomFill_Location, myDegmax, mySegmax );
686       result = MkSw.Shape();
687       myErrorOnSurf = MkSw.ErrorOnSurface();
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       BuildHistory(MkSw, theOriginalS);
747     }
748   }
749       
750   if ( TheS.ShapeType() == TopAbs_FACE ) {
751     Standard_Integer ii, jj;
752     //jgv
753     TopExp_Explorer Explo(result, TopAbs_FACE);
754     for (; Explo.More(); Explo.Next())
755     {
756       TopoDS_Shape aFace = Explo.Current();
757       RebuildTopOrBottomFace(aFace.Reversed(), Standard_True); //top face was reversed
758     }
759     /////
760     TopoDS_Face F;
761     for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
762       for (jj=1; jj<=myFaces->RowLength(); jj++) {
763         if (myFaces->Value(ii, jj).ShapeType() == TopAbs_FACE)
764         {
765           F = TopoDS::Face(myFaces->Value(ii, jj));
766           if (!F.IsNull()) B.Add(result, F);
767         }
768       }
769     }
770
771     if ( !mySpine.Closed()) {
772       // if Spine is not closed 
773       // add the last face of the solid
774
775       //jgv
776       RebuildTopOrBottomFace(TheLast, Standard_False); //bottom face
777       /////
778       B.Add(result, TopoDS::Face(TheLast));
779     }
780
781     TopoDS_Solid solid;
782     BRep_Builder BS;
783     BS.MakeSolid(solid);
784
785     result.Closed(Standard_True);
786     BS.Add(solid,TopoDS::Shell(result));
787
788     BRepClass3d_SolidClassifier SC(solid);
789     SC.PerformInfinitePoint(Precision::Confusion());
790     if ( SC.State() == TopAbs_IN) {
791       BS.MakeSolid(solid);
792       TopoDS_Shape aLocalShape = result.Reversed();
793       BS.Add(solid,TopoDS::Shell(aLocalShape));
794 //      BS.Add(solid,TopoDS::Shell(result.Reversed()));
795     }
796     UpdateMap(theOriginalS, solid, myGenMap);
797     return solid;
798   }
799   else {
800     return result;
801   }
802 }
803
804 //============================================================================
805 //function : FindEdge
806 //purpose  : Find the number of edge corresponding to the edge of the profile.
807 //============================================================================
808
809 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
810                                          const TopoDS_Edge& E,
811                                          Standard_Integer& InitialLength) const
812 {
813   Standard_Integer result = 0;
814
815   switch (S.ShapeType()) {
816           
817   case TopAbs_EDGE :
818     {
819       InitialLength++;
820       if (S.IsSame(E)) result = InitialLength;
821       break;
822     }
823           
824   case TopAbs_WIRE :
825     {
826       Handle(BRepFill_ShapeLaw) Section = 
827         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
828       Standard_Integer NbLaw = Section->NbLaw();
829
830       for (Standard_Integer ii = 1; (ii<=NbLaw) && (!result); ii++) {
831         if (E.IsSame(Section->Edge(ii)) ) result = InitialLength + ii;
832       }
833       InitialLength += NbLaw;
834       break;
835     }
836
837   case TopAbs_FACE :
838   case TopAbs_SHELL :
839   case TopAbs_COMPOUND :
840     {
841      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
842        result = FindEdge(it.Value(), E, InitialLength );
843      break;
844     }
845
846   case TopAbs_SOLID :
847   case TopAbs_COMPSOLID :
848     throw Standard_DomainError("BRepFill_Pipe::SOLID or COMPSOLID");
849     break;
850   default:
851     break;
852   }
853
854   return result; 
855 }
856
857 //=======================================================================
858 //function : FindVertex
859 //purpose  : Find the number of edge corresponding to an edge of the profile.
860 //=======================================================================
861
862 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
863                                            const TopoDS_Vertex& V,
864                                            Standard_Integer& InitialLength) const
865 {
866   Standard_Integer result = 0;
867
868   switch (S.ShapeType()) {
869   case TopAbs_VERTEX :
870     {
871       InitialLength++;
872       if (S.IsSame(V)) result = InitialLength;
873       break;
874     }
875           
876   case TopAbs_EDGE :
877     {
878       TopoDS_Vertex VF, VL;
879       TopExp::Vertices(TopoDS::Edge(S), VF, VL);
880       if (S.Orientation() == TopAbs_REVERSED) {
881         TopoDS_Vertex aux;
882         aux = VF; VF = VL; VL = aux;
883       }
884       if (VF.IsSame(V)) result = InitialLength+1;
885       else if (VL.IsSame(V)) result = InitialLength+2;
886       InitialLength += 2;
887       break;
888     }
889           
890   case TopAbs_WIRE :
891     {
892       Standard_Integer ii = InitialLength+1;
893       Handle(BRepFill_ShapeLaw) Section = 
894         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
895       InitialLength += Section->NbLaw()+1;
896      
897       for (; (ii<=InitialLength) && (!result); ii++) {
898         if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
899       }
900       break;
901     }
902
903   case TopAbs_FACE :
904   case TopAbs_SHELL :
905   case TopAbs_COMPOUND :
906     {
907      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
908        result = FindVertex(it.Value(), V, InitialLength);
909      break;
910     }
911
912   case TopAbs_SOLID :
913   case TopAbs_COMPSOLID :
914     throw Standard_DomainError("BRepFill_Pipe::SOLID or COMPSOLID");
915     break;
916   default:
917     break;
918   }
919
920   return result; 
921 }
922
923 //=======================================================================
924 //function : DefineRealSegmax
925 //purpose  : Defines the real number of segments
926 //           required in the case of bspline spine
927 //=======================================================================
928
929 void BRepFill_Pipe::DefineRealSegmax()
930 {
931   Standard_Integer RealSegmax = 0;
932
933   TopoDS_Iterator iter(mySpine);
934   for (; iter.More(); iter.Next())
935     {
936       TopoDS_Edge E = TopoDS::Edge(iter.Value());
937       Standard_Real first, last;
938       Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
939       if (C.IsNull())
940         continue;
941       while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
942              C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
943         {
944           if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
945             C = Handle(Geom_TrimmedCurve)::DownCast (C)->BasisCurve();
946           if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
947             C = Handle(Geom_OffsetCurve)::DownCast (C)->BasisCurve();
948         }
949       if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
950         {
951           Handle(Geom_BSplineCurve) BC (Handle(Geom_BSplineCurve)::DownCast (C));
952           Standard_Integer NbKnots = BC->NbKnots();
953           Standard_Integer RealNbKnots = NbKnots;
954           if (first > BC->FirstParameter())
955             {
956               Standard_Integer I1, I2;
957               BC->LocateU( first, Precision::PConfusion(), I1, I2 );
958               RealNbKnots -= I1-1;
959             }
960           if (last < BC->LastParameter())
961             {
962               Standard_Integer I1, I2;
963               BC->LocateU( last, Precision::PConfusion(), I1, I2 );
964               RealNbKnots -= NbKnots-I2;
965             }
966           RealSegmax += RealNbKnots-1;
967         }
968     }
969
970   if (mySegmax < RealSegmax)
971     mySegmax = RealSegmax;
972 }
973
974 //=======================================================================
975 //function : RebuildTopOrBottomFace
976 //purpose  : Correct orientation of v-iso edges
977 //           according to new 3d and 2d curves taken from swept surfaces
978 //=======================================================================
979
980 void BRepFill_Pipe::RebuildTopOrBottomFace(const TopoDS_Shape& aFace,
981                                            const Standard_Boolean IsTop) const
982 {
983   Standard_Integer IndexOfSection =
984     (IsTop)? 1 : mySections->RowLength();
985
986   Standard_Integer ii;
987   BRep_Builder BB;
988   TopoDS_Iterator itf(aFace);
989   for (; itf.More(); itf.Next())
990   {
991     TopoDS_Shape aWire = itf.Value();
992     TopTools_SequenceOfShape InitEdges;
993     TopTools_SequenceOfShape ResEdges;
994     TopoDS_Iterator itw(aWire);
995     for (; itw.More(); itw.Next())
996     {
997       TopoDS_Shape anEdge = itw.Value();
998       for (ii = myCurIndexOfSectionEdge; ii <= mySections->ColLength(); ii++)
999       {
1000         TopoDS_Shape aVisoEdge = mySections->Value(ii, IndexOfSection);
1001         if (anEdge.IsSame(aVisoEdge))
1002         {
1003           InitEdges.Append(anEdge);
1004           ResEdges.Append(aVisoEdge);
1005           break;
1006         }
1007       }
1008     }
1009     aWire.Free(Standard_True);
1010     for (ii = 1; ii <= InitEdges.Length(); ii++)
1011     {
1012       BB.Remove(aWire, InitEdges(ii));
1013       UpdateTolFromTopOrBottomPCurve(TopoDS::Face(aFace), TopoDS::Edge(ResEdges(ii)));
1014       BB.Add(aWire, ResEdges(ii));
1015     }
1016   }
1017 }
1018
1019 //=======================================================================
1020 //function : BuildHistory
1021 //purpose  : Builds history for edges and vertices
1022 //           of section and path
1023 //=======================================================================
1024 void BRepFill_Pipe::BuildHistory(const BRepFill_Sweep& theSweep,
1025                                  const TopoDS_Shape&   theSection)
1026 {
1027   //Filling of <myGenMap>
1028   const Handle(TopTools_HArray2OfShape)& anUEdges = theSweep.InterFaces();
1029   
1030   Standard_Integer inde;
1031   TopoDS_Iterator itw;
1032
1033   if (theSection.ShapeType() == TopAbs_WIRE)
1034   {
1035     TopoDS_Wire aSection = TopoDS::Wire(theSection);
1036     BRepTools_WireExplorer wexp_sec(aSection);
1037     for (inde = 0; wexp_sec.More(); wexp_sec.Next())
1038     {
1039       inde++;
1040       const TopoDS_Edge& anEdge = TopoDS::Edge(wexp_sec.Current());
1041       if (BRep_Tool::Degenerated(anEdge))
1042         continue;
1043       if (myGenMap.IsBound(anEdge))
1044         continue;
1045       
1046       TopoDS_Vertex aVertex [2];
1047       TopExp::Vertices(anEdge, aVertex[0], aVertex[1]);
1048       
1049       //For an edge generated shape is a "tape" -
1050       //a shell usually containing this edge and
1051       //passing from beginning of path to its end
1052       TopoDS_Shell aTape = TopoDS::Shell(theSweep.Tape(inde));
1053       
1054       //Processing of vertices of <anEdge>
1055       //We should choose right index in <anUEdges>
1056       //for each vertex of edge 
1057       Standard_Integer UIndex [2];
1058       UIndex[0] = inde;
1059       UIndex[1] = inde+1;
1060       
1061       if (anEdge.Orientation() == TopAbs_REVERSED)
1062       { Standard_Integer Tmp = UIndex[0]; UIndex[0] = UIndex[1]; UIndex[1] = Tmp; }
1063       
1064       for (Standard_Integer kk = 0; kk < 2; kk++)
1065       {
1066         if (myGenMap.IsBound(aVertex[kk]))
1067           continue;
1068         
1069         //Assemble the list of edges ("rail" along the path)
1070         TopTools_ListOfShape* Elist = myGenMap.Bound(aVertex[kk], TopTools_ListOfShape());
1071         Standard_Integer jj;
1072         for (jj = 1; jj <= anUEdges->UpperCol(); jj++)
1073         {
1074           const TopoDS_Shape& anUedge = anUEdges->Value(UIndex[kk], jj);
1075           if (!anUedge.IsNull())
1076             Elist->Append(anUedge);
1077         }
1078       } //for (Standard_Integer kk = 0; kk < 2; kk++)
1079       
1080       TopTools_ListOfShape* Flist = myGenMap.Bound(anEdge, TopTools_ListOfShape());
1081       TopoDS_Iterator itsh(aTape);
1082       for (; itsh.More(); itsh.Next())
1083         Flist->Append(itsh.Value());
1084     } //for (inde = 0; wexp_sec.More(); wexp_sec.Next())
1085   } //if (theSection.ShapeType() == TopAbs_WIRE)
1086
1087   //For subshapes of spine
1088   const Handle(TopTools_HArray2OfShape)& aFaces  = theSweep.SubShape();
1089   const Handle(TopTools_HArray2OfShape)& aVEdges = theSweep.Sections();
1090   
1091   BRepTools_WireExplorer wexp(mySpine);
1092   inde = 0;
1093   Standard_Boolean ToExit = Standard_False;
1094   for (;;)
1095   {
1096     if (!wexp.More())
1097       ToExit = Standard_True;
1098     
1099     inde++;
1100
1101     if (!ToExit)
1102     {
1103       const TopoDS_Edge& anEdgeOfSpine = wexp.Current();
1104       for (Standard_Integer i = 1; i <= aFaces->UpperRow(); i++)
1105       {
1106         const TopoDS_Shape& aFace = aFaces->Value(i, inde);
1107         UpdateMap(anEdgeOfSpine, aFace, myGenMap);
1108       }
1109     }
1110     
1111     const TopoDS_Vertex& aVertexOfSpine = wexp.CurrentVertex();
1112     for (Standard_Integer i = 1; i <= aVEdges->UpperRow(); i++)
1113     {
1114       const TopoDS_Shape& aVedge = aVEdges->Value(i, inde);
1115       UpdateMap(aVertexOfSpine, aVedge, myGenMap);
1116     }
1117
1118     if (ToExit)
1119       break;
1120
1121     if (wexp.More())
1122       wexp.Next();
1123   }
1124 }