0029939: Modeling Algorithms - add NULL check to BRepGProp_Face::Load()
[occt.git] / src / BRepGProp / BRepGProp_Face.cxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Bnd_Box2d.hxx>
17 #include <BndLib_Add2dCurve.hxx>
18 #include <BRepGProp_Face.hxx>
19 #include <Geom2d_BezierCurve.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <Geom2d_Line.hxx>
22 #include <Geom_BezierSurface.hxx>
23 #include <Geom_BSplineCurve.hxx>
24 #include <Geom_BSplineSurface.hxx>
25 #include <Geom_SurfaceOfLinearExtrusion.hxx>
26 #include <GeomAdaptor_Curve.hxx>
27 #include <gp_Pnt.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <gp_Vec.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <math.hxx>
32 #include <Precision.hxx>
33 #include <TopoDS.hxx>
34 #include <TopoDS_Edge.hxx>
35 #include <TopoDS_Face.hxx>
36
37 static const Standard_Real Epsilon1 = Epsilon(1.);
38
39 //=======================================================================
40 //function : UIntegrationOrder
41 //purpose  : 
42 //=======================================================================
43 Standard_Integer BRepGProp_Face::UIntegrationOrder() const {
44
45   Standard_Integer Nu;
46   switch (mySurface.GetType())
47   {
48
49   case GeomAbs_Plane :
50     Nu =4;
51     break;
52
53   case GeomAbs_BezierSurface :
54     {
55       Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
56       Nu = Max(4,Nu);
57     }
58     break;
59   case GeomAbs_BSplineSurface :
60     {
61       Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree()+1;
62       Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots()-1;
63       Nu = Max(4,a*b);
64     }
65     break;
66
67   default :
68     Nu = 9;
69     break;
70   }
71  return Max(8,2*Nu);
72 }
73
74 //=======================================================================
75 //function : VIntegrationOrder
76 //purpose  : 
77 //=======================================================================
78
79 Standard_Integer BRepGProp_Face::VIntegrationOrder() const
80 {
81  Standard_Integer Nv;
82  switch (mySurface.GetType()) {
83
84  case GeomAbs_Plane :
85    Nv = 4;
86    break;
87
88  case GeomAbs_BezierSurface :
89    {
90    Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
91    Nv = Max(4,Nv);
92    }
93    break;
94
95  case GeomAbs_BSplineSurface :
96    {
97    Standard_Integer a = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree()+1;
98    Standard_Integer b = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots()-1;
99    Nv = Max(4,a*b);
100    }
101    break;
102
103    default :
104      Nv = 9;
105    break;
106  }
107  return Max(8,2*Nv);
108 }
109
110 //=======================================================================
111 //function : IntegrationOrder
112 //purpose  : 
113 //=======================================================================
114
115 Standard_Integer BRepGProp_Face::IntegrationOrder() const 
116 {
117   Standard_Integer N;
118
119   switch (myCurve.GetType()) {
120     
121   case GeomAbs_Line :
122     N = 2;
123     break;
124
125   case GeomAbs_Circle :
126   case GeomAbs_Ellipse :
127   case GeomAbs_Hyperbola :
128     N = 9;
129     break;
130
131   case GeomAbs_Parabola :
132     N = 9;
133     break;
134
135   case GeomAbs_BezierCurve :
136     {
137       N = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree() + 1;
138     }
139     break;
140
141   case GeomAbs_BSplineCurve :
142     {
143     Standard_Integer a = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree() + 1;
144     Standard_Integer b = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots() - 1;
145     N = a * b;
146     }
147     break;
148
149     default :
150       N = 9;
151     break;
152   }
153
154   return Max(4,2*N);
155 }
156
157 //=======================================================================
158 //function : Bounds
159 //purpose  : 
160 //=======================================================================
161
162 void BRepGProp_Face::Bounds(Standard_Real& U1,
163                             Standard_Real& U2,
164                             Standard_Real& V1,
165                             Standard_Real& V2)const 
166 {
167   U1 = mySurface.FirstUParameter();
168   U2 = mySurface.LastUParameter();
169   V1 = mySurface.FirstVParameter();
170   V2 = mySurface.LastVParameter();
171 }
172
173 //=======================================================================
174 //function : Load
175 //purpose  : 
176 //=======================================================================
177
178 bool BRepGProp_Face::Load(const TopoDS_Edge& E)
179
180   Standard_Real a,b;
181   Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
182   if (C.IsNull())
183   {
184     return false;
185   }
186   if (E.Orientation() == TopAbs_REVERSED) { 
187     Standard_Real x = a;
188     a = C->ReversedParameter(b);
189     b = C->ReversedParameter(x);
190     C = C->Reversed();
191   }
192   myCurve.Load(C,a,b);
193   return true;
194 }
195
196 //=======================================================================
197 //function : Load
198 //purpose  : 
199 //=======================================================================
200
201 void BRepGProp_Face::Load(const TopoDS_Face& F) 
202
203   TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
204   mySurface.Initialize(TopoDS::Face(aLocalShape));
205 //  mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
206   mySReverse = (F.Orientation() == TopAbs_REVERSED);
207 }
208
209 //=======================================================================
210 //function : Normal
211 //purpose  : 
212 //=======================================================================
213
214 void BRepGProp_Face::Normal (const Standard_Real  U,
215                              const Standard_Real  V,
216                                    gp_Pnt        &P,
217                                    gp_Vec        &VNor) const 
218 {
219   gp_Vec D1U,D1V;
220   mySurface.D1(U,V,P,D1U,D1V);
221   VNor = D1U.Crossed(D1V);
222   if (mySReverse) VNor.Reverse();
223   
224 }
225
226 //  APO 17.04.2002 (OCC104)
227 // This is functions that calculate coeff. to optimize "integration order".
228 //They had been produced experementally for some hard example.
229 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
230 static inline Standard_Real SCoeff(const Standard_Real Eps){
231   return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
232 }
233 static inline Standard_Real LCoeff(const Standard_Real Eps){
234   return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
235 }
236
237 //=======================================================================
238 //function : SIntOrder
239 //purpose  : 
240 //=======================================================================
241
242 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
243 {
244   Standard_Integer Nv, Nu;
245   switch (mySurface.GetType()) {
246   case GeomAbs_Plane:  
247     Nu = 1; Nv = 1; break;
248   case GeomAbs_Cylinder: 
249     Nu = 2; Nv = 1; break;
250   case GeomAbs_Cone: 
251     Nu = 2; Nv = 1; break;
252   case GeomAbs_Sphere: 
253     Nu = 2; Nv = 2; break;
254   case GeomAbs_Torus:
255     Nu = 2; Nv = 2; break;
256   case GeomAbs_BezierSurface: 
257     Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
258     Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
259     break;
260   case GeomAbs_BSplineSurface: 
261     Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
262     Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
263     break;
264   default:  
265     Nu = 2; Nv = 2;  break;
266   }
267   return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
268 }
269
270 //=======================================================================
271 //function : SUIntSubs
272 //purpose  : 
273 //=======================================================================
274
275 Standard_Integer BRepGProp_Face::SUIntSubs() const
276 {
277   Standard_Integer N;
278   switch (mySurface.GetType()) {
279   case GeomAbs_Plane:  
280     N = 2;  break;
281   case GeomAbs_Cylinder: 
282     N = 4;  break;
283   case GeomAbs_Cone: 
284     N = 4;  break;
285   case GeomAbs_Sphere: 
286     N = 4; break;
287   case GeomAbs_Torus:
288     N = 4; break;
289   case GeomAbs_BezierSurface:  
290     N = 2;  break;
291   case GeomAbs_BSplineSurface: 
292     N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots();  break;
293   default:  
294     N = 2;  break;
295   }
296   return N - 1;
297 }
298
299 //=======================================================================
300 //function : SVIntSubs
301 //purpose  : 
302 //=======================================================================
303
304 Standard_Integer BRepGProp_Face::SVIntSubs() const
305 {
306   Standard_Integer N;
307   switch (mySurface.GetType()) {
308   case GeomAbs_Plane:  
309     N = 2;  break;
310   case GeomAbs_Cylinder: 
311     N = 2;  break;
312   case GeomAbs_Cone: 
313     N = 2;  break;
314   case GeomAbs_Sphere: 
315     N = 3; break;
316   case GeomAbs_Torus:
317     N = 4; break;
318   case GeomAbs_BezierSurface: 
319     N = 2;  break;
320   case GeomAbs_BSplineSurface: 
321     N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
322     break;
323   default:  
324     N = 2;  break;
325   }
326   return N - 1;
327 }
328
329 //=======================================================================
330 //function : UKnots
331 //purpose  : 
332 //=======================================================================
333
334 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
335 {
336   switch (mySurface.GetType()) {
337   case GeomAbs_Plane:
338     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();  
339     break;
340   case GeomAbs_Cylinder: 
341   case GeomAbs_Cone: 
342   case GeomAbs_Sphere: 
343   case GeomAbs_Torus:
344     Knots(1) = 0.0;  Knots(2) = M_PI*2.0/3.0;  Knots(3) = M_PI*4.0/3.0;  Knots(4) = M_PI*6.0/3.0;
345     break;
346   case GeomAbs_BSplineSurface: 
347     (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
348     break;
349   default: 
350     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();
351     break;
352   }  
353 }
354
355 //=======================================================================
356 //function : VKnots
357 //purpose  : 
358 //=======================================================================
359
360 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
361 {
362   switch (mySurface.GetType()) {
363   case GeomAbs_Plane:
364   case GeomAbs_Cylinder: 
365   case GeomAbs_Cone: 
366     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();  
367     break;
368   case GeomAbs_Sphere: 
369     Knots(1) = -M_PI/2.0;  Knots(2) = 0.0;  Knots(3) = +M_PI/2.0;
370     break;
371   case GeomAbs_Torus:
372     Knots(1) = 0.0;  Knots(2) = M_PI*2.0/3.0;  Knots(3) = M_PI*4.0/3.0;  Knots(4) = M_PI*6.0/3.0;
373     break;
374   case GeomAbs_BSplineSurface: 
375     (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
376     break;
377   default: 
378     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();
379     break;
380   }  
381 }
382
383 //=======================================================================
384 //function : LIntOrder
385 //purpose  : 
386 //=======================================================================
387
388 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
389 {
390   Bnd_Box2d aBox;
391
392   BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
393   Standard_Real aXmin, aXmax, aYmin, aYmax;
394   aBox.Get(aXmin, aYmin, aXmax, aYmax);
395   Standard_Real aVmin = mySurface.FirstVParameter();
396   Standard_Real aVmax = mySurface.LastVParameter();
397
398   Standard_Real dv = (aVmax-aVmin);
399   Standard_Real anR = (dv > Epsilon1 ? Min ((aYmax - aYmin) / dv, 1.) : 1.);
400
401 //  Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
402   Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
403   Standard_Integer aLSubs = LIntSubs();
404
405
406 //  Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
407   Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
408   switch (myCurve.GetType()) {
409   case GeomAbs_Line:  
410     NL = 1;  break;
411   case GeomAbs_Circle:
412     NL = 2 * 3;  break; //correction for the spans of converted curve
413   case GeomAbs_Ellipse:
414     NL = 2 * 3;  break; //
415   case GeomAbs_Parabola:  
416     NL = 2 * 3;  break;
417   case GeomAbs_Hyperbola: 
418     NL = 3 * 3;  break;
419   case GeomAbs_BezierCurve: 
420     NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
421     break;
422   case GeomAbs_BSplineCurve: 
423     NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
424     break;
425   default:  
426     NL = 3 * 3;  break;
427   }
428
429   NL = Max(NL, NS);
430
431   Standard_Integer nn = 
432     RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
433
434   //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
435   return Min(nn, math::GaussPointsMax());
436 }
437
438 //=======================================================================
439 //function : LIntSubs
440 //purpose  : 
441 //=======================================================================
442
443 Standard_Integer BRepGProp_Face::LIntSubs() const
444 {
445   Standard_Integer N;
446   switch (myCurve.GetType()) {
447   case GeomAbs_Line:  
448     N = 2;  break;
449   case GeomAbs_Circle:
450   case GeomAbs_Ellipse:
451     N = 4;  break;
452   case GeomAbs_Parabola:
453   case GeomAbs_Hyperbola:
454     N = 2;  break;
455   case GeomAbs_BSplineCurve: 
456     N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
457     break;
458   default:  
459     N = 2;  break;
460   }
461   return N - 1;
462 }
463
464 //=======================================================================
465 //function : LKnots
466 //purpose  : 
467 //=======================================================================
468
469 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
470 {
471   switch (myCurve.GetType()) {
472   case GeomAbs_Line:  
473     Knots(1) = myCurve.FirstParameter();  Knots(2) = myCurve.LastParameter();
474     break;
475   case GeomAbs_Circle:
476   case GeomAbs_Ellipse:
477     Knots(1) = 0.0;  Knots(2) = M_PI*2.0/3.0;  Knots(3) = M_PI*4.0/3.0;  Knots(4) = M_PI*6.0/3.0;
478     break;
479   case GeomAbs_Parabola:
480   case GeomAbs_Hyperbola:
481     Knots(1) = myCurve.FirstParameter();  Knots(2) = myCurve.LastParameter();
482     break;
483   case GeomAbs_BSplineCurve:
484     (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
485     break;
486   default: 
487     Knots(1) = myCurve.FirstParameter();  Knots(2) = myCurve.LastParameter();
488     break;
489   }  
490 }
491
492 //=======================================================================
493 //function : Load
494 //purpose  : 
495 //=======================================================================
496
497 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
498                           const GeomAbs_IsoType  theIsoType) 
499 {
500   Standard_Real aLen;
501   Standard_Real aU1;
502   Standard_Real aU2;
503   Standard_Real aV1;
504   Standard_Real aV2;
505   gp_Pnt2d      aLoc;
506   gp_Dir2d      aDir;
507
508   Bounds(aU1, aU2, aV1, aV2);
509
510   if (theIsoType == GeomAbs_IsoU) {
511     aLen = aV2 - aV1;
512
513     if (IsFirstParam) {
514       aLoc.SetCoord(aU1, aV2);
515       aDir.SetCoord(0., -1.);
516     } else {
517       aLoc.SetCoord(aU2, aV1);
518       aDir.SetCoord(0., 1.);
519     }
520   } else if (theIsoType == GeomAbs_IsoV) {
521     aLen = aU2 - aU1;
522
523     if (IsFirstParam) {
524       aLoc.SetCoord(aU1, aV1);
525       aDir.SetCoord(1., 0.);
526     } else {
527       aLoc.SetCoord(aU2, aV2);
528       aDir.SetCoord(-1., 0.);
529     }
530   } else
531     return;
532
533   Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
534
535   myCurve.Load(aLin, 0., aLen);
536 }
537
538 //=======================================================================
539 //function : GetRealKnots
540 //purpose  : 
541 //=======================================================================
542
543 static void GetRealKnots(const Standard_Real                  theMin,
544                          const Standard_Real                  theMax,
545                          const Handle(TColStd_HArray1OfReal) &theKnots,
546                                Handle(TColStd_HArray1OfReal) &theRealKnots)
547 {
548   Standard_Integer i       = theKnots->Lower() - 1;
549   Standard_Integer iU      = theKnots->Upper();
550   Standard_Integer aStartI = 0;
551   Standard_Integer aEndI   = 0;
552   Standard_Real    aTol    = Precision::Confusion();
553
554   while (++i < iU) {
555     if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
556       aStartI = i;
557
558     if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
559       aEndI = i;
560
561     if (aStartI != 0 && aEndI != 0)
562       break;
563   }
564
565   if (aStartI == 0)
566     aStartI = iU;
567
568   Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
569   Standard_Integer j;
570
571   theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
572   theRealKnots->SetValue(1,       theMin);
573   theRealKnots->SetValue(aNbNode, theMax);
574
575
576   for (i = 2, j = aStartI; j <= aEndI; i++, j++)
577     theRealKnots->SetValue(i, theKnots->Value(j));
578 }
579
580 //=======================================================================
581 //function : GetCurveKnots
582 //purpose  : 
583 //=======================================================================
584
585 static void GetCurveKnots(const Standard_Real                  theMin,
586                           const Standard_Real                  theMax,
587                           const Geom2dAdaptor_Curve           &theCurve,
588                                 Handle(TColStd_HArray1OfReal) &theKnots)
589 {
590   Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
591
592   if (isSBSpline) {
593     Handle(Geom2d_BSplineCurve)   aCrv;
594     Standard_Integer              aNbKnots;
595     Handle(TColStd_HArray1OfReal) aCrvKnots;
596
597     aCrv     = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
598     aNbKnots = aCrv->NbKnots();
599     aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
600     aCrv->Knots(aCrvKnots->ChangeArray1());
601     GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
602   } else {
603     theKnots = new TColStd_HArray1OfReal(1, 2);
604     theKnots->SetValue(1, theMin);
605     theKnots->SetValue(2, theMax);
606   }
607 }
608
609 //=======================================================================
610 //function : GetUKnots
611 //purpose  : 
612 //=======================================================================
613
614 void BRepGProp_Face::GetUKnots
615                      (const Standard_Real                  theUMin,
616                       const Standard_Real                  theUMax,
617                             Handle(TColStd_HArray1OfReal) &theUKnots) const
618 {
619   Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
620   Standard_Boolean isCBSpline = Standard_False;
621
622   if (!isSBSpline) {
623     // Check the basis curve of the surface of linear extrusion.
624     if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
625       GeomAdaptor_Curve    aCurve;
626       Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
627
628       aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
629       isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
630     }
631   }
632
633   if (myIsUseSpan && (isSBSpline || isCBSpline)) {
634     // Using span decomposition for BSpline.
635     Handle(TColStd_HArray1OfReal) aKnots;
636     Standard_Integer              aNbKnots;
637
638     if (isSBSpline) {
639       // Get U knots of BSpline surface.
640       Handle(Geom_Surface)        aSurf = mySurface.Surface().Surface();
641       Handle(Geom_BSplineSurface) aBSplSurf;
642
643       aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
644       aNbKnots  = aBSplSurf->NbUKnots();
645       aKnots    = new TColStd_HArray1OfReal(1, aNbKnots);
646       aBSplSurf->UKnots(aKnots->ChangeArray1());
647     } else {
648       // Get U knots of BSpline curve - basis curve of
649       // the surface of linear extrusion.
650       GeomAdaptor_Curve         aCurve;
651       Handle(Geom_Surface)      aSurf = mySurface.Surface().Surface();
652       Handle(Geom_BSplineCurve) aBSplCurve;
653
654       aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
655       aBSplCurve = aCurve.BSpline();
656       aNbKnots   = aBSplCurve->NbKnots();
657       aKnots     = new TColStd_HArray1OfReal(1, aNbKnots);
658       aBSplCurve->Knots(aKnots->ChangeArray1());
659     }
660
661     // Compute number of knots inside theUMin and theUMax.
662     GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
663   } else {
664     // No span decomposition.
665     theUKnots = new TColStd_HArray1OfReal(1, 2);
666     theUKnots->SetValue(1, theUMin);
667     theUKnots->SetValue(2, theUMax);
668   }
669 }
670
671 //=======================================================================
672 //function : GetTKnots
673 //purpose  : 
674 //=======================================================================
675
676 void BRepGProp_Face::GetTKnots
677                      (const Standard_Real                  theTMin,
678                       const Standard_Real                  theTMax,
679                             Handle(TColStd_HArray1OfReal) &theTKnots) const
680 {
681   Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
682
683   if (myIsUseSpan && isBSpline) {
684     // Using span decomposition for BSpline.
685     Handle(TColStd_HArray1OfReal) aSurfKnots;
686     Standard_Integer              aNbKnots;
687
688     // Get V knots of BSpline surface.
689     Handle(Geom_Surface)        aSurf = mySurface.Surface().Surface();
690     Handle(Geom_BSplineSurface) aBSplSurf;
691
692     aBSplSurf  = Handle(Geom_BSplineSurface)::DownCast(aSurf);
693     aNbKnots   = aBSplSurf->NbVKnots();
694     aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
695     aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
696
697 //     Handle(TColStd_HArray1OfReal) aCurveKnots;
698
699 //     GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
700 //    GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
701     GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
702   } else {
703     theTKnots = new TColStd_HArray1OfReal(1, 2);
704     theTKnots->SetValue(1, theTMin);
705     theTKnots->SetValue(2, theTMax);
706   }
707 }