0027033: Modeling -- ensure stable result of area calculation
[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 void BRepGProp_Face::Load(const TopoDS_Edge& E) 
179
180   Standard_Real a,b;
181   Handle(Geom2d_Curve) C = 
182     BRep_Tool::CurveOnSurface(E, mySurface.Face(), a,b);
183   if (E.Orientation() == TopAbs_REVERSED) { 
184     Standard_Real x = a;
185     a = C->ReversedParameter(b);
186     b = C->ReversedParameter(x);
187     C = C->Reversed();
188   }
189   myCurve.Load(C,a,b);
190 }
191
192 //=======================================================================
193 //function : Load
194 //purpose  : 
195 //=======================================================================
196
197 void BRepGProp_Face::Load(const TopoDS_Face& F) 
198
199   TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
200   mySurface.Initialize(TopoDS::Face(aLocalShape));
201 //  mySurface.Initialize(TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
202   mySReverse = (F.Orientation() == TopAbs_REVERSED);
203 }
204
205 //=======================================================================
206 //function : Normal
207 //purpose  : 
208 //=======================================================================
209
210 void BRepGProp_Face::Normal (const Standard_Real  U,
211                              const Standard_Real  V,
212                                    gp_Pnt        &P,
213                                    gp_Vec        &VNor) const 
214 {
215   gp_Vec D1U,D1V;
216   mySurface.D1(U,V,P,D1U,D1V);
217   VNor = D1U.Crossed(D1V);
218   if (mySReverse) VNor.Reverse();
219   
220 }
221
222 //  APO 17.04.2002 (OCC104)
223 // This is functions that calculate coeff. to optimize "integration order".
224 //They had been produced experementally for some hard example.
225 static Standard_Real AS = -0.15, AL = -0.50, B = 1.0, C = 0.75, D = 0.25;
226 static inline Standard_Real SCoeff(const Standard_Real Eps){
227   return Eps < 0.1? AS*(B+Log10(Eps)) + C: C;
228 }
229 static inline Standard_Real LCoeff(const Standard_Real Eps){
230   return Eps < 0.1? AL*(B+Log10(Eps)) + D: D;
231 }
232
233 //=======================================================================
234 //function : SIntOrder
235 //purpose  : 
236 //=======================================================================
237
238 Standard_Integer BRepGProp_Face::SIntOrder(const Standard_Real Eps) const
239 {
240   Standard_Integer Nv, Nu;
241   switch (mySurface.GetType()) {
242   case GeomAbs_Plane:  
243     Nu = 1; Nv = 1; break;
244   case GeomAbs_Cylinder: 
245     Nu = 2; Nv = 1; break;
246   case GeomAbs_Cone: 
247     Nu = 2; Nv = 1; break;
248   case GeomAbs_Sphere: 
249     Nu = 2; Nv = 2; break;
250   case GeomAbs_Torus:
251     Nu = 2; Nv = 2; break;
252   case GeomAbs_BezierSurface: 
253     Nv = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
254     Nu = (*((Handle(Geom_BezierSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
255     break;
256   case GeomAbs_BSplineSurface: 
257     Nv = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VDegree();
258     Nu = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UDegree();
259     break;
260   default:  
261     Nu = 2; Nv = 2;  break;
262   }
263   return Min(RealToInt(Ceiling(SCoeff(Eps)*Max((Nu+1),(Nv+1)))), math::GaussPointsMax());
264 }
265
266 //=======================================================================
267 //function : SUIntSubs
268 //purpose  : 
269 //=======================================================================
270
271 Standard_Integer BRepGProp_Face::SUIntSubs() const
272 {
273   Standard_Integer N;
274   switch (mySurface.GetType()) {
275   case GeomAbs_Plane:  
276     N = 2;  break;
277   case GeomAbs_Cylinder: 
278     N = 4;  break;
279   case GeomAbs_Cone: 
280     N = 4;  break;
281   case GeomAbs_Sphere: 
282     N = 4; break;
283   case GeomAbs_Torus:
284     N = 4; break;
285   case GeomAbs_BezierSurface:  
286     N = 2;  break;
287   case GeomAbs_BSplineSurface: 
288     N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbUKnots();  break;
289   default:  
290     N = 2;  break;
291   }
292   return N - 1;
293 }
294
295 //=======================================================================
296 //function : SVIntSubs
297 //purpose  : 
298 //=======================================================================
299
300 Standard_Integer BRepGProp_Face::SVIntSubs() const
301 {
302   Standard_Integer N;
303   switch (mySurface.GetType()) {
304   case GeomAbs_Plane:  
305     N = 2;  break;
306   case GeomAbs_Cylinder: 
307     N = 2;  break;
308   case GeomAbs_Cone: 
309     N = 2;  break;
310   case GeomAbs_Sphere: 
311     N = 3; break;
312   case GeomAbs_Torus:
313     N = 4; break;
314   case GeomAbs_BezierSurface: 
315     N = 2;  break;
316   case GeomAbs_BSplineSurface: 
317     N = (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->NbVKnots();
318     break;
319   default:  
320     N = 2;  break;
321   }
322   return N - 1;
323 }
324
325 //=======================================================================
326 //function : UKnots
327 //purpose  : 
328 //=======================================================================
329
330 void BRepGProp_Face::UKnots(TColStd_Array1OfReal& Knots) const
331 {
332   switch (mySurface.GetType()) {
333   case GeomAbs_Plane:
334     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();  
335     break;
336   case GeomAbs_Cylinder: 
337   case GeomAbs_Cone: 
338   case GeomAbs_Sphere: 
339   case GeomAbs_Torus:
340     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;
341     break;
342   case GeomAbs_BSplineSurface: 
343     (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->UKnots(Knots);
344     break;
345   default: 
346     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();
347     break;
348   }  
349 }
350
351 //=======================================================================
352 //function : VKnots
353 //purpose  : 
354 //=======================================================================
355
356 void BRepGProp_Face::VKnots(TColStd_Array1OfReal& Knots) const
357 {
358   switch (mySurface.GetType()) {
359   case GeomAbs_Plane:
360   case GeomAbs_Cylinder: 
361   case GeomAbs_Cone: 
362     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();  
363     break;
364   case GeomAbs_Sphere: 
365     Knots(1) = -M_PI/2.0;  Knots(2) = 0.0;  Knots(3) = +M_PI/2.0;
366     break;
367   case GeomAbs_Torus:
368     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;
369     break;
370   case GeomAbs_BSplineSurface: 
371     (*((Handle(Geom_BSplineSurface)*)&((mySurface.Surface()).Surface())))->VKnots(Knots);
372     break;
373   default: 
374     Knots(1) = mySurface.FirstUParameter();  Knots(2) = mySurface.LastUParameter();
375     break;
376   }  
377 }
378
379 //=======================================================================
380 //function : LIntOrder
381 //purpose  : 
382 //=======================================================================
383
384 Standard_Integer BRepGProp_Face::LIntOrder(const Standard_Real Eps) const
385 {
386   Bnd_Box2d aBox;
387
388   BndLib_Add2dCurve::Add(myCurve, 1.e-7, aBox);
389   Standard_Real aXmin, aXmax, aYmin, aYmax;
390   aBox.Get(aXmin, aYmin, aXmax, aYmax);
391   Standard_Real aVmin = mySurface.FirstVParameter();
392   Standard_Real aVmax = mySurface.LastVParameter();
393
394   Standard_Real dv = (aVmax-aVmin);
395   Standard_Real anR = (dv > Epsilon1 ? Min ((aYmax - aYmin) / dv, 1.) : 1.);
396
397 //  Standard_Integer anRInt = Max(RealToInt(Ceiling(SVIntSubs()*anR)), 2);
398   Standard_Integer anRInt = RealToInt(Ceiling(SVIntSubs()*anR));
399   Standard_Integer aLSubs = LIntSubs();
400
401
402 //  Standard_Real NL, NS = Max(SIntOrder(1.0)*anRInt/LIntSubs(), 1);
403   Standard_Real NL, NS = Max(SIntOrder(1.)*anRInt/aLSubs, 1);
404   switch (myCurve.GetType()) {
405   case GeomAbs_Line:  
406     NL = 1;  break;
407   case GeomAbs_Circle:
408     NL = 2 * 3;  break; //correction for the spans of converted curve
409   case GeomAbs_Ellipse:
410     NL = 2 * 3;  break; //
411   case GeomAbs_Parabola:  
412     NL = 2 * 3;  break;
413   case GeomAbs_Hyperbola: 
414     NL = 3 * 3;  break;
415   case GeomAbs_BezierCurve: 
416     NL = (*((Handle(Geom2d_BezierCurve)*)&(myCurve.Curve())))->Degree();
417     break;
418   case GeomAbs_BSplineCurve: 
419     NL = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Degree();
420     break;
421   default:  
422     NL = 3 * 3;  break;
423   }
424
425   NL = Max(NL, NS);
426
427   Standard_Integer nn = 
428     RealToInt (aLSubs <= 4 ? Ceiling(LCoeff(Eps)*(NL+1)) : NL+1);
429
430   //return Min(RealToInt(Ceiling(LCoeff(Eps)*(NL+1)*NS)), math::GaussPointsMax());
431   return Min(nn, math::GaussPointsMax());
432 }
433
434 //=======================================================================
435 //function : LIntSubs
436 //purpose  : 
437 //=======================================================================
438
439 Standard_Integer BRepGProp_Face::LIntSubs() const
440 {
441   Standard_Integer N;
442   switch (myCurve.GetType()) {
443   case GeomAbs_Line:  
444     N = 2;  break;
445   case GeomAbs_Circle:
446   case GeomAbs_Ellipse:
447     N = 4;  break;
448   case GeomAbs_Parabola:
449   case GeomAbs_Hyperbola:
450     N = 2;  break;
451   case GeomAbs_BSplineCurve: 
452     N = (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->NbKnots();
453     break;
454   default:  
455     N = 2;  break;
456   }
457   return N - 1;
458 }
459
460 //=======================================================================
461 //function : LKnots
462 //purpose  : 
463 //=======================================================================
464
465 void BRepGProp_Face::LKnots(TColStd_Array1OfReal& Knots) const
466 {
467   switch (myCurve.GetType()) {
468   case GeomAbs_Line:  
469     Knots(1) = myCurve.FirstParameter();  Knots(2) = myCurve.LastParameter();
470     break;
471   case GeomAbs_Circle:
472   case GeomAbs_Ellipse:
473     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;
474     break;
475   case GeomAbs_Parabola:
476   case GeomAbs_Hyperbola:
477     Knots(1) = myCurve.FirstParameter();  Knots(2) = myCurve.LastParameter();
478     break;
479   case GeomAbs_BSplineCurve:
480     (*((Handle(Geom2d_BSplineCurve)*)&(myCurve.Curve())))->Knots(Knots);
481     break;
482   default: 
483     Knots(1) = myCurve.FirstParameter();  Knots(2) = myCurve.LastParameter();
484     break;
485   }  
486 }
487
488 //=======================================================================
489 //function : Load
490 //purpose  : 
491 //=======================================================================
492
493 void BRepGProp_Face::Load(const Standard_Boolean IsFirstParam,
494                           const GeomAbs_IsoType  theIsoType) 
495 {
496   Standard_Real aLen;
497   Standard_Real aU1;
498   Standard_Real aU2;
499   Standard_Real aV1;
500   Standard_Real aV2;
501   gp_Pnt2d      aLoc;
502   gp_Dir2d      aDir;
503
504   Bounds(aU1, aU2, aV1, aV2);
505
506   if (theIsoType == GeomAbs_IsoU) {
507     aLen = aV2 - aV1;
508
509     if (IsFirstParam) {
510       aLoc.SetCoord(aU1, aV2);
511       aDir.SetCoord(0., -1.);
512     } else {
513       aLoc.SetCoord(aU2, aV1);
514       aDir.SetCoord(0., 1.);
515     }
516   } else if (theIsoType == GeomAbs_IsoV) {
517     aLen = aU2 - aU1;
518
519     if (IsFirstParam) {
520       aLoc.SetCoord(aU1, aV1);
521       aDir.SetCoord(1., 0.);
522     } else {
523       aLoc.SetCoord(aU2, aV2);
524       aDir.SetCoord(-1., 0.);
525     }
526   } else
527     return;
528
529   Handle(Geom2d_Curve) aLin = new Geom2d_Line(aLoc, aDir);
530
531   myCurve.Load(aLin, 0., aLen);
532 }
533
534 //=======================================================================
535 //function : GetRealKnots
536 //purpose  : 
537 //=======================================================================
538
539 static void GetRealKnots(const Standard_Real                  theMin,
540                          const Standard_Real                  theMax,
541                          const Handle(TColStd_HArray1OfReal) &theKnots,
542                                Handle(TColStd_HArray1OfReal) &theRealKnots)
543 {
544   Standard_Integer i       = theKnots->Lower() - 1;
545   Standard_Integer iU      = theKnots->Upper();
546   Standard_Integer aStartI = 0;
547   Standard_Integer aEndI   = 0;
548   Standard_Real    aTol    = Precision::Confusion();
549
550   while (++i < iU) {
551     if (aStartI == 0 && theKnots->Value(i) > theMin + aTol)
552       aStartI = i;
553
554     if (aEndI == 0 && theKnots->Value(i + 1) > theMax - aTol)
555       aEndI = i;
556
557     if (aStartI != 0 && aEndI != 0)
558       break;
559   }
560
561   if (aStartI == 0)
562     aStartI = iU;
563
564   Standard_Integer aNbNode = Max(0, aEndI - aStartI + 1) + 2;
565   Standard_Integer j;
566
567   theRealKnots = new TColStd_HArray1OfReal(1, aNbNode);
568   theRealKnots->SetValue(1,       theMin);
569   theRealKnots->SetValue(aNbNode, theMax);
570
571
572   for (i = 2, j = aStartI; j <= aEndI; i++, j++)
573     theRealKnots->SetValue(i, theKnots->Value(j));
574 }
575
576 //=======================================================================
577 //function : GetCurveKnots
578 //purpose  : 
579 //=======================================================================
580
581 static void GetCurveKnots(const Standard_Real                  theMin,
582                           const Standard_Real                  theMax,
583                           const Geom2dAdaptor_Curve           &theCurve,
584                                 Handle(TColStd_HArray1OfReal) &theKnots)
585 {
586   Standard_Boolean isSBSpline = theCurve.GetType() == GeomAbs_BSplineCurve;
587
588   if (isSBSpline) {
589     Handle(Geom2d_BSplineCurve)   aCrv;
590     Standard_Integer              aNbKnots;
591     Handle(TColStd_HArray1OfReal) aCrvKnots;
592
593     aCrv     = Handle(Geom2d_BSplineCurve)::DownCast(theCurve.Curve());
594     aNbKnots = aCrv->NbKnots();
595     aCrvKnots = new TColStd_HArray1OfReal(1, aNbKnots);
596     aCrv->Knots(aCrvKnots->ChangeArray1());
597     GetRealKnots(theMin, theMax, aCrvKnots, theKnots);
598   } else {
599     theKnots = new TColStd_HArray1OfReal(1, 2);
600     theKnots->SetValue(1, theMin);
601     theKnots->SetValue(2, theMax);
602   }
603 }
604
605 //=======================================================================
606 //function : GetUKnots
607 //purpose  : 
608 //=======================================================================
609
610 void BRepGProp_Face::GetUKnots
611                      (const Standard_Real                  theUMin,
612                       const Standard_Real                  theUMax,
613                             Handle(TColStd_HArray1OfReal) &theUKnots) const
614 {
615   Standard_Boolean isSBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
616   Standard_Boolean isCBSpline = Standard_False;
617
618   if (!isSBSpline) {
619     // Check the basis curve of the surface of linear extrusion.
620     if (mySurface.GetType() == GeomAbs_SurfaceOfExtrusion) {
621       GeomAdaptor_Curve    aCurve;
622       Handle(Geom_Surface) aSurf = mySurface.Surface().Surface();
623
624       aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
625       isCBSpline = aCurve.GetType() == GeomAbs_BSplineCurve;
626     }
627   }
628
629   if (myIsUseSpan && (isSBSpline || isCBSpline)) {
630     // Using span decomposition for BSpline.
631     Handle(TColStd_HArray1OfReal) aKnots;
632     Standard_Integer              aNbKnots;
633
634     if (isSBSpline) {
635       // Get U knots of BSpline surface.
636       Handle(Geom_Surface)        aSurf = mySurface.Surface().Surface();
637       Handle(Geom_BSplineSurface) aBSplSurf;
638
639       aBSplSurf = Handle(Geom_BSplineSurface)::DownCast(aSurf);
640       aNbKnots  = aBSplSurf->NbUKnots();
641       aKnots    = new TColStd_HArray1OfReal(1, aNbKnots);
642       aBSplSurf->UKnots(aKnots->ChangeArray1());
643     } else {
644       // Get U knots of BSpline curve - basis curve of
645       // the surface of linear extrusion.
646       GeomAdaptor_Curve         aCurve;
647       Handle(Geom_Surface)      aSurf = mySurface.Surface().Surface();
648       Handle(Geom_BSplineCurve) aBSplCurve;
649
650       aCurve.Load(Handle(Geom_SurfaceOfLinearExtrusion)::DownCast (aSurf)->BasisCurve());
651       aBSplCurve = aCurve.BSpline();
652       aNbKnots   = aBSplCurve->NbKnots();
653       aKnots     = new TColStd_HArray1OfReal(1, aNbKnots);
654       aBSplCurve->Knots(aKnots->ChangeArray1());
655     }
656
657     // Compute number of knots inside theUMin and theUMax.
658     GetRealKnots(theUMin, theUMax, aKnots, theUKnots);
659   } else {
660     // No span decomposition.
661     theUKnots = new TColStd_HArray1OfReal(1, 2);
662     theUKnots->SetValue(1, theUMin);
663     theUKnots->SetValue(2, theUMax);
664   }
665 }
666
667 //=======================================================================
668 //function : GetTKnots
669 //purpose  : 
670 //=======================================================================
671
672 void BRepGProp_Face::GetTKnots
673                      (const Standard_Real                  theTMin,
674                       const Standard_Real                  theTMax,
675                             Handle(TColStd_HArray1OfReal) &theTKnots) const
676 {
677   Standard_Boolean isBSpline = mySurface.GetType() == GeomAbs_BSplineSurface;
678
679   if (myIsUseSpan && isBSpline) {
680     // Using span decomposition for BSpline.
681     Handle(TColStd_HArray1OfReal) aSurfKnots;
682     Standard_Integer              aNbKnots;
683
684     // Get V knots of BSpline surface.
685     Handle(Geom_Surface)        aSurf = mySurface.Surface().Surface();
686     Handle(Geom_BSplineSurface) aBSplSurf;
687
688     aBSplSurf  = Handle(Geom_BSplineSurface)::DownCast(aSurf);
689     aNbKnots   = aBSplSurf->NbVKnots();
690     aSurfKnots = new TColStd_HArray1OfReal(1, aNbKnots);
691     aBSplSurf->VKnots(aSurfKnots->ChangeArray1());
692
693 //     Handle(TColStd_HArray1OfReal) aCurveKnots;
694
695 //     GetCurveKnots(theTMin, theTMax, myCurve, aCurveKnots);
696 //    GetRealCurveKnots(aCurveKnots, aSurfKnots, myCurve, theTKnots);
697     GetCurveKnots(theTMin, theTMax, myCurve, theTKnots);
698   } else {
699     theTKnots = new TColStd_HArray1OfReal(1, 2);
700     theTKnots->SetValue(1, theTMin);
701     theTKnots->SetValue(2, theTMax);
702   }
703 }