0023643: Intersection algorithm produces B-Spline curve in case of coaxial cones
[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-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #include <BRepFill_Pipe.ixx>
23
24 #include <Standard_ErrorHandler.hxx>
25
26 #include <BRep_Tool.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRepClass3d_SolidClassifier.hxx>
29 #include <BRepLib_MakeVertex.hxx>
30
31 #include <GeomFill_CorrectedFrenet.hxx>
32 #include <GeomFill_CurveAndTrihedron.hxx>
33
34 #include <BRepFill_SectionPlacement.hxx>
35 #include <BRepFill_ShapeLaw.hxx>
36 #include <BRepFill_Edge3DLaw.hxx>
37 #include <BRepFill_Sweep.hxx>
38
39 #include <GeomAbs_Shape.hxx>
40 #include <TopExp.hxx>
41 #include <TopAbs_ShapeEnum.hxx>
42 #include <TopoDS.hxx>
43 #include <TopoDS_Shell.hxx>
44 #include <TopoDS_Solid.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopoDS_Iterator.hxx>
47
48 #include <Precision.hxx>
49 #include <Standard_NotImplemented.hxx>
50
51 #include <Geom_TrimmedCurve.hxx>
52 #include <Geom_OffsetCurve.hxx>
53 #include <Geom_BSplineCurve.hxx>
54
55 #ifdef DRAW
56 #include <DBRep.hxx>
57 static Standard_Boolean Affich = 0;
58 #endif
59
60 //=======================================================================
61 //function : BRepFill_Pipe
62 //purpose  : 
63 //=======================================================================
64
65 BRepFill_Pipe::BRepFill_Pipe()
66 {
67   myDegmax = 10;
68   mySegmax = 100;
69 }
70
71
72 //=======================================================================
73 //function : BRepFill_Pipe
74 //purpose  : 
75 //=======================================================================
76
77 BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire&  Spine,
78                              const TopoDS_Shape& Profile,
79                              const Standard_Boolean KPart)
80 {
81   myDegmax = 10;
82   mySegmax = 100;
83   Perform(Spine, Profile, KPart);
84 }
85
86
87
88 //=======================================================================
89 //function : Perform
90 //purpose  : 
91 //=======================================================================
92
93 void BRepFill_Pipe::Perform(const TopoDS_Wire&  Spine,
94                             const TopoDS_Shape& Profile,
95                             const Standard_Boolean KPart)
96
97 {
98   mySections.Nullify();
99   myFaces.Nullify();
100   myEdges.Nullify();
101
102   mySpine   = Spine;
103   myProfile = Profile;
104
105   DefineRealSegmax();
106
107   BRepTools_WireExplorer wexp;
108   TopoDS_Shape TheProf; 
109
110
111  Handle(GeomFill_CorrectedFrenet) TLaw = 
112    new (GeomFill_CorrectedFrenet) ();
113   Handle(GeomFill_CurveAndTrihedron) Loc = 
114     new (GeomFill_CurveAndTrihedron) (TLaw);
115   myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc);
116   if (myLoc->NbLaw() == 0) {
117     return; // Degenerated case
118   }
119   myLoc->TransformInG0Law(); // Set into continuity
120     
121   BRepFill_SectionPlacement Place(myLoc, Profile);
122   myTrsf = Place.Transformation();
123
124   TopLoc_Location Loc2(myTrsf), Loc1;
125   Loc1 = Profile.Location();
126   TopoDS_Shape aux;
127   TheProf =  myProfile;
128   TheProf.Location(Loc2.Multiplied(Loc1));
129  
130   // Construct First && Last Shape
131   Handle(GeomFill_LocationLaw) law;
132
133   gp_Mat M;
134   gp_Vec V;
135   gp_Trsf fila;
136   Standard_Real first, last;
137   myLoc->Law(1)->GetDomain(first, last);
138   myLoc->Law(1)->D0(first, M, V);
139     fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
140                    M(2,1), M(2,2), M(2,3), V.Y(),
141                    M(3,1), M(3,2), M(3,3), V.Z(),
142                    1.e-12, 1.e-14);
143
144   fila.Multiply(myTrsf);
145   TopLoc_Location LocFirst(fila);
146   myFirst = myProfile;
147   if ( ! LocFirst.IsIdentity()) {
148     myFirst.Location( LocFirst.Multiplied(myProfile.Location()) );
149   }
150
151   myLoc->Law(myLoc->NbLaw())->GetDomain(first, last);
152   myLoc->Law(myLoc->NbLaw())->D0(last,M, V);
153 //    try { // Not good, but there are no other means to test SetValues
154   fila.SetValues(M(1,1), M(1,2), M(1,3), V.X(),
155                  M(2,1), M(2,2), M(2,3), V.Y(),
156                  M(3,1), M(3,2), M(3,3), V.Z(),
157                  1.e-12, 1.e-14);
158   fila.Multiply(myTrsf);
159   TopLoc_Location LocLast(fila);
160   if (! myLoc->IsClosed() || LocFirst != LocLast) {
161     myLast = myProfile;
162     if ( ! LocLast.IsIdentity()) {
163       myLast.Location(LocLast.Multiplied(myProfile.Location()) );
164     }
165   }
166   else {
167     myLast = myFirst;
168   }
169 #if DRAW
170   if (Affich) {
171     DBRep::Set("theprof",  TheProf);
172     DBRep::Set("thefirst", myFirst);
173     DBRep::Set("thelast" , myLast);
174  }
175 #endif
176  
177   myShape = MakeShape(TheProf, myFirst, myLast);
178 }
179
180
181 //=======================================================================
182 //function : Spine
183 //purpose  : 
184 //=======================================================================
185
186 const TopoDS_Shape& BRepFill_Pipe::Spine() const 
187 {
188   return mySpine;
189 }
190
191 //=======================================================================
192 //function : Profile
193 //purpose  : 
194 //=======================================================================
195
196 const TopoDS_Shape& BRepFill_Pipe::Profile() const 
197 {
198   return myProfile;
199 }
200
201 //=======================================================================
202 //function : Shape
203 //purpose  : 
204 //=======================================================================
205
206 const TopoDS_Shape& BRepFill_Pipe::Shape() const 
207 {
208   return myShape;
209 }
210
211
212 //=======================================================================
213 //function : FirstShape
214 //purpose  : 
215 //=======================================================================
216
217 const TopoDS_Shape& BRepFill_Pipe::FirstShape() const 
218 {
219   return myFirst;
220 }
221
222
223 //=======================================================================
224 //function : LastShape
225 //purpose  : 
226 //=======================================================================
227
228 const TopoDS_Shape& BRepFill_Pipe::LastShape() const 
229 {
230   return myLast;
231 }
232
233
234 //=======================================================================
235 //function : Face
236 //purpose  : 
237 //=======================================================================
238
239 TopoDS_Face BRepFill_Pipe::Face(const TopoDS_Edge& ESpine,
240                                 const TopoDS_Edge& EProfile)
241 {
242   TopoDS_Face theFace;
243
244   if ( BRep_Tool::Degenerated(EProfile))
245     return theFace;
246
247   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;
248
249   // *************************************************
250   // Search if EProfile is an edge of myProfile
251   // *************************************************
252   iprof = FindEdge(myProfile, EProfile, count);
253
254   if (!iprof) Standard_DomainError::Raise(
255               "BRepFill_Pipe::Face : Edge not in the Profile");
256
257
258   // *************************************************
259   // Search if ESpine  is an edge of mySpine and find 
260   // the index of the corresponding Filler
261   // *************************************************
262  for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
263     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
264
265   if (!ispin) Standard_DomainError::Raise(
266     "BRepFill_Pipe::Edge  : Edge not in the Spine");
267
268   theFace = TopoDS::Face(myFaces->Value(iprof, ispin));
269   return theFace;
270
271 }
272
273 //=======================================================================
274 //function : Edge
275 //purpose  : 
276 //=======================================================================
277 TopoDS_Edge BRepFill_Pipe::Edge(const TopoDS_Edge&   ESpine,
278                                 const TopoDS_Vertex& VProfile)
279 {
280   Standard_Integer ii, ispin = 0, iprof = 0, count = 0;;
281
282   // *************************************************
283   // Search if VProfile is a Vertex of myProfile
284   // *************************************************
285   iprof = FindVertex(myProfile, VProfile, count);
286   if (!iprof) Standard_DomainError::Raise(
287         "BRepFill_Pipe::Edge : Vertex not in the Profile");
288
289
290   // *************************************************
291   // Search if ESpine  is an edge of mySpine and find 
292   // the index of the corresponding Filler
293   // *************************************************
294    
295   for (ii=1; ii<=myLoc->NbLaw() && (!ispin); ii++) 
296     if  (ESpine.IsSame(myLoc->Edge(ii))) ispin = ii;
297
298   if (!ispin) Standard_DomainError::Raise(
299     "BRepFill_Pipe::Edge  : Edge not in the Spine");
300
301
302   // *************************************************
303   // Generate the corresponding Shape
304   // *************************************************  
305   TopoDS_Edge theEdge;
306   theEdge = TopoDS::Edge(myEdges->Value(iprof, ispin));
307
308   return theEdge;
309
310 }
311
312
313 //=======================================================================
314 //function : Section
315 //purpose  : 
316 //=======================================================================
317
318 TopoDS_Shape BRepFill_Pipe::Section(const TopoDS_Vertex& VSpine) const 
319 {
320   TopoDS_Iterator it, itv;
321
322   Standard_Integer ii, ispin = 0;
323
324   TopoDS_Shape curSect = myProfile;
325
326   // *************************************************
327   // Search if ESpine  is an edge of mySpine and find 
328   // the index of the corresponding Filler
329   // *************************************************
330
331   // iterate on all the edges of mySpine
332  for (ii=1; ii<=myLoc->NbLaw()+1 && (!ispin); ii++) 
333     if  (VSpine.IsSame(myLoc->Vertex(ii))) ispin = ii;
334
335   if (!ispin) Standard_DomainError::Raise(
336     "BRepFill_Pipe::Section  : Vertex not in the Spine");
337
338   BRep_Builder B;
339   TopoDS_Compound Comp; 
340   B.MakeCompound(Comp);
341   for (ii=1; ii<=mySections->ColLength(); ii++)
342     B.Add(Comp, mySections->Value(ii, ispin));
343   
344   return Comp;
345 }
346
347 //=======================================================================
348 //function : PipeLine
349 //purpose  : Construct a wire by sweeping of a point
350 //=======================================================================
351
352 TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const
353 {
354  // Postioning 
355  gp_Pnt P;
356  P = Point;
357  P.Transform(myTrsf);
358
359  BRepLib_MakeVertex MkV(P); 
360  Handle(BRepFill_ShapeLaw) Section = 
361         new (BRepFill_ShapeLaw) (MkV.Vertex());
362
363  // Sweeping
364  BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
365  MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
366  TopoDS_Shape aLocalShape = MkSw.Shape();
367  return TopoDS::Wire(aLocalShape);
368 // return TopoDS::Wire(MkSw.Shape());
369 }
370
371 //=======================================================================
372 //function : MakeShape
373 //purpose  : 
374 //=======================================================================
375
376 TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S,
377                                       const TopoDS_Shape& FirstShape,
378                                       const TopoDS_Shape& LastShape)
379 {
380   TopoDS_Shape result;
381   BRep_Builder B;
382   Standard_Boolean explode = Standard_False; 
383   TopoDS_Shape TheS, TheFirst, TheLast;
384   Standard_Integer InitialLength = 0;
385   TheS = S;
386   TheFirst = FirstShape;
387   TheLast = LastShape;
388   if (! myFaces.IsNull()) InitialLength = myFaces->ColLength();
389
390   // there are two kinds of generation
391   //  1. generate with S from each Filler (Vertex, Edge)
392   //  2. call MakeShape recursively on the subshapes of S
393   //
394   // explode is True in the second case
395
396   // create the result empty
397
398   switch (S.ShapeType()) {
399
400   case TopAbs_VERTEX :
401     {
402       B.MakeWire(TopoDS::Wire(result));
403       break;
404     }
405           
406   case TopAbs_EDGE :
407     {
408       TopoDS_Wire W;
409       B.MakeShell(TopoDS::Shell(result));
410       B.MakeWire(W);
411       B.Add(W, S);
412       W.Closed(S.Closed());
413       TheS = W;
414       if (!FirstShape.IsNull()) {
415         B.MakeWire(W);
416         B.Add(W, FirstShape);
417         W.Closed(FirstShape.Closed());
418         TheFirst = W;
419       }
420       if (!LastShape.IsNull()) {
421         B.MakeWire(W);
422         B.Add(W, LastShape);
423         W.Closed(LastShape.Closed());
424         TheLast = W;
425       }
426       break;
427     }
428           
429   case TopAbs_WIRE :
430     B.MakeShell(TopoDS::Shell(result));
431     break;
432
433   case TopAbs_FACE :
434     {
435       B.MakeShell(TopoDS::Shell(result));
436       explode = Standard_True;
437       if ( !mySpine.Closed() && !TheFirst.IsNull()) {
438          B.Add(result, TheFirst.Reversed());
439       }
440       break;
441     }
442
443   case TopAbs_SHELL :
444     {
445       B.MakeCompSolid(TopoDS::CompSolid(result));
446       explode = Standard_True;
447       break;
448     }
449
450   case TopAbs_SOLID :
451   case TopAbs_COMPSOLID :
452     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
453     break;
454
455   case TopAbs_COMPOUND :
456     {
457       B.MakeCompound(TopoDS::Compound(result));
458       explode = Standard_True;
459       break;
460     }
461   default:
462     break;
463   }
464
465   if (explode) {
466     // add the subshapes
467     TopoDS_Iterator itFirst, itLast;
468     TopoDS_Shape first, last;
469     if (!TheFirst.IsNull()) itFirst.Initialize(TheFirst);
470     if (!TheLast.IsNull()) itLast.Initialize(TheLast);
471
472     for (TopoDS_Iterator it(S); it.More(); it.Next()) {
473       if (!TheFirst.IsNull()) first = itFirst.Value();
474       if (!TheLast.IsNull())  last = itLast.Value();
475       if (TheS.ShapeType() == TopAbs_FACE ) 
476         MakeShape(it.Value(), first, last);
477       else
478         B.Add(result,MakeShape(it.Value(), first, last));
479
480       if (!TheFirst.IsNull()) itFirst.Next();
481       if (!TheLast.IsNull())  itLast.Next();
482     }
483   }
484   
485   else {
486     if (TheS.ShapeType() == TopAbs_VERTEX ) {
487      Handle(BRepFill_ShapeLaw) Section = 
488         new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS));
489       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
490       MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
491       result = MkSw.Shape();
492     }
493
494     if (TheS.ShapeType() == TopAbs_WIRE ) {
495       Handle(BRepFill_ShapeLaw) Section = 
496         new (BRepFill_ShapeLaw) (TopoDS::Wire(TheS));
497       BRepFill_Sweep MkSw(Section, myLoc, Standard_True);
498       MkSw.SetBounds(TopoDS::Wire(TheFirst), 
499                      TopoDS::Wire(TheLast));
500       MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax );
501       result = MkSw.Shape();
502
503       // Labeling of elements
504       if (mySections.IsNull()) {
505         myFaces    = MkSw.SubShape();
506         mySections = MkSw.Sections();
507         myEdges    = MkSw.InterFaces();
508       }
509       else {
510         Handle(TopTools_HArray2OfShape) Aux, Somme;
511         Standard_Integer length;
512         Standard_Integer ii, jj, kk;
513
514         Aux = MkSw.SubShape();
515         length = Aux->ColLength() + myFaces->ColLength(); 
516         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
517                                                Aux->RowLength());
518         for (jj=1; jj<=myFaces->RowLength(); jj++) {
519           for (ii=1; ii<=myFaces->ColLength(); ii++)
520             Somme->SetValue(ii, jj, myFaces->Value(ii, jj));
521  
522           for (kk=1, ii=myFaces->ColLength()+1; 
523                kk <=Aux->ColLength(); kk++, ii++)
524             Somme->SetValue(ii, jj, Aux->Value(kk, jj));
525         }
526         myFaces = Somme;    
527        
528
529         Aux = MkSw.Sections();
530         length = Aux->ColLength() + mySections->ColLength(); 
531         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
532                                                Aux->RowLength());
533         for (jj=1; jj<=mySections->RowLength(); jj++) {
534           for (ii=1; ii<=mySections->ColLength(); ii++)
535             Somme->SetValue(ii, jj, mySections->Value(ii, jj));
536  
537           for (kk=1, ii=mySections->ColLength()+1; 
538                kk <=Aux->ColLength(); kk++, ii++)
539             Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
540         }
541         mySections = Somme;
542
543         Aux = MkSw.InterFaces();
544         length = Aux->ColLength() + myEdges->ColLength(); 
545         Somme = new (TopTools_HArray2OfShape) (1, length, 1, 
546                                                Aux->RowLength());
547         for (jj=1; jj<=myEdges->RowLength(); jj++) {
548           for (ii=1; ii<=myEdges->ColLength(); ii++)
549             Somme->SetValue(ii, jj, myEdges->Value(ii, jj));
550  
551           for (kk=1, ii=myEdges->ColLength()+1; 
552                kk <=Aux->ColLength(); kk++, ii++)
553             Somme->SetValue(ii, jj, Aux->Value(kk, jj));   
554         }
555         myEdges = Somme;               
556       }
557     }
558   }
559       
560   if ( TheS.ShapeType() == TopAbs_FACE ) {
561     Standard_Integer ii, jj;
562     TopoDS_Face F;
563     for (ii=InitialLength+1; ii<=myFaces->ColLength(); ii++) {
564       for (jj=1; jj<=myFaces->RowLength(); jj++) {
565         F = TopoDS::Face(myFaces->Value(ii, jj));
566         if (!F.IsNull()) B.Add(result, F);
567       }
568     }
569
570     if ( !mySpine.Closed()) {
571       // if Spine is not closed 
572       // add the last face of the solid
573       B.Add(result, TopoDS::Face(TheLast));
574     }
575
576     TopoDS_Solid solid;
577     BRep_Builder BS;
578     BS.MakeSolid(solid);
579
580     result.Closed(Standard_True);
581     BS.Add(solid,TopoDS::Shell(result));
582
583     BRepClass3d_SolidClassifier SC(solid);
584     SC.PerformInfinitePoint(Precision::Confusion());
585     if ( SC.State() == TopAbs_IN) {
586       BS.MakeSolid(solid);
587       TopoDS_Shape aLocalShape = result.Reversed();
588       BS.Add(solid,TopoDS::Shell(aLocalShape));
589 //      BS.Add(solid,TopoDS::Shell(result.Reversed()));
590     }
591     return solid;
592   }
593   else {
594     return result;
595   }
596   return result;
597 }
598
599 //============================================================================
600 //function : FindEdge
601 //purpose  : Find the number of edge corresponding to the edge of the profile.
602 //============================================================================
603
604 Standard_Integer BRepFill_Pipe::FindEdge(const TopoDS_Shape& S,
605                                          const TopoDS_Edge& E,
606                                          Standard_Integer& InitialLength) const
607 {
608   Standard_Integer result = 0;
609
610   switch (S.ShapeType()) {
611           
612   case TopAbs_EDGE :
613     {
614       InitialLength++;
615       if (S.IsSame(E)) result = InitialLength;
616       break;
617     }
618           
619   case TopAbs_WIRE :
620     {
621       Standard_Integer ii = InitialLength+1;
622       Handle(BRepFill_ShapeLaw) Section = 
623         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
624       InitialLength += Section->NbLaw();
625      
626       for (; (ii<=InitialLength) && (!result); ii++) {
627         if (E.IsSame(Section->Edge(ii)) ) result = ii;
628       }
629       break;
630     }
631
632   case TopAbs_FACE :
633   case TopAbs_SHELL :
634   case TopAbs_COMPOUND :
635     {
636      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
637        result = FindEdge(it.Value(), E, InitialLength );
638      break;
639     }
640
641   case TopAbs_SOLID :
642   case TopAbs_COMPSOLID :
643     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
644     break;
645   default:
646     break;
647   }
648
649   return result; 
650 }
651
652 //=======================================================================
653 //function : FindVertex
654 //purpose  : Find the number of edge corresponding to an edge of the profile.
655 //=======================================================================
656
657 Standard_Integer BRepFill_Pipe::FindVertex(const TopoDS_Shape& S,
658                                            const TopoDS_Vertex& V,
659                                            Standard_Integer& InitialLength) const
660 {
661   Standard_Integer result = 0;
662
663   switch (S.ShapeType()) {
664   case TopAbs_VERTEX :
665     {
666       InitialLength++;
667       if (S.IsSame(V)) result = InitialLength;
668       break;
669     }
670           
671   case TopAbs_EDGE :
672     {
673       TopoDS_Vertex VF, VL;
674       TopExp::Vertices(TopoDS::Edge(S), VF, VL);
675       if (S.Orientation() == TopAbs_REVERSED) {
676         TopoDS_Vertex aux;
677         aux = VF; VF = VL; VL = aux;
678       }
679       if (VF.IsSame(V)) result = InitialLength+1;
680       else if (VL.IsSame(V)) result = InitialLength+2;
681       InitialLength += 2;
682       break;
683     }
684           
685   case TopAbs_WIRE :
686     {
687       Standard_Integer ii = InitialLength+1;
688       Handle(BRepFill_ShapeLaw) Section = 
689         new (BRepFill_ShapeLaw) (TopoDS::Wire(S), Standard_False);
690       InitialLength += Section->NbLaw()+1;
691      
692       for (; (ii<=InitialLength) && (!result); ii++) {
693         if (V.IsSame(Section->Vertex(ii, 0.)) ) result = ii;
694       }
695       break;
696     }
697
698   case TopAbs_FACE :
699   case TopAbs_SHELL :
700   case TopAbs_COMPOUND :
701     {
702      for (TopoDS_Iterator it(S); it.More() && (!result); it.Next())
703        result = FindVertex(it.Value(), V, InitialLength);
704      break;
705     }
706
707   case TopAbs_SOLID :
708   case TopAbs_COMPSOLID :
709     Standard_DomainError::Raise("BRepFill_Pipe::SOLID or COMPSOLID");
710     break;
711   default:
712     break;
713   }
714
715   return result; 
716 }
717
718 //=======================================================================
719 //function : DefineRealSegmax
720 //purpose  : Defines the real number of segments
721 //           required in the case of bspline spine
722 //=======================================================================
723
724 void BRepFill_Pipe::DefineRealSegmax()
725 {
726   Standard_Integer RealSegmax = 0;
727
728   TopoDS_Iterator iter(mySpine);
729   for (; iter.More(); iter.Next())
730     {
731       TopoDS_Edge E = TopoDS::Edge(iter.Value());
732       Standard_Real first, last;
733       Handle(Geom_Curve) C = BRep_Tool::Curve( E, first, last );
734       if (C.IsNull())
735         continue;
736       while (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve) ||
737              C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
738         {
739           if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
740             C = (*((Handle(Geom_TrimmedCurve)*)&C))->BasisCurve();
741           if (C->DynamicType() == STANDARD_TYPE(Geom_OffsetCurve))
742             C = (*((Handle(Geom_OffsetCurve)*)&C))->BasisCurve();
743         }
744       if (C->DynamicType() == STANDARD_TYPE(Geom_BSplineCurve))
745         {
746           const Handle(Geom_BSplineCurve)& BC = *((Handle(Geom_BSplineCurve)*)&C);
747           Standard_Integer NbKnots = BC->NbKnots();
748           Standard_Integer RealNbKnots = NbKnots;
749           if (first > BC->FirstParameter())
750             {
751               Standard_Integer I1, I2;
752               BC->LocateU( first, Precision::PConfusion(), I1, I2 );
753               RealNbKnots -= I1-1;
754             }
755           if (last < BC->LastParameter())
756             {
757               Standard_Integer I1, I2;
758               BC->LocateU( last, Precision::PConfusion(), I1, I2 );
759               RealNbKnots -= NbKnots-I2;
760             }
761           RealSegmax += RealNbKnots-1;
762         }
763     }
764
765   if (mySegmax < RealSegmax)
766     mySegmax = RealSegmax;
767 }