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