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