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