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