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