0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / Geom / Geom_OffsetSurface.cxx
1 // Created on: 1991-06-25
2 // Created by: JCV
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // Modified     04/10/96 : JCT : derivee des surfaces offset utilisation de
18 //                               CSLib
19 // Modified     15/11/96 : JPI : ajout equivalent surface pour les surfaces canoniques et modif des methodes D0 D1, ... UIso,VIso
20 // Modified     18/11/96 : JPI : inversion de l'offsetValue dans UReverse et Vreverse
21
22 #include <AdvApprox_ApproxAFunction.hxx>
23 #include <BSplCLib.hxx>
24 #include <BSplSLib.hxx>
25 #include <Convert_GridPolynomialToPoles.hxx>
26 #include <CSLib.hxx>
27 #include <Geom_BezierSurface.hxx>
28 #include <Geom_BSplineCurve.hxx>
29 #include <Geom_BSplineSurface.hxx>
30 #include <Geom_Circle.hxx>
31 #include <Geom_ConicalSurface.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_CylindricalSurface.hxx>
34 #include <Geom_ElementarySurface.hxx>
35 #include <Geom_Ellipse.hxx>
36 #include <Geom_Geometry.hxx>
37 #include <Geom_OffsetCurve.hxx>
38 #include <Geom_OffsetSurface.hxx>
39 #include <Geom_Plane.hxx>
40 #include <Geom_RectangularTrimmedSurface.hxx>
41 #include <Geom_SphericalSurface.hxx>
42 #include <Geom_Surface.hxx>
43 #include <Geom_SurfaceOfLinearExtrusion.hxx>
44 #include <Geom_SurfaceOfRevolution.hxx>
45 #include <Geom_ToroidalSurface.hxx>
46 #include <Geom_TrimmedCurve.hxx>
47 #include <Geom_UndefinedDerivative.hxx>
48 #include <Geom_UndefinedValue.hxx>
49 #include <GeomAbs_CurveType.hxx>
50 #include <GeomAbs_IsoType.hxx>
51 #include <GeomAbs_Shape.hxx>
52 #include <GeomAdaptor_Surface.hxx>
53 #include <GeomEvaluator_OffsetSurface.hxx>
54 #include <gp.hxx>
55 #include <gp_Dir.hxx>
56 #include <gp_GTrsf2d.hxx>
57 #include <gp_Pnt.hxx>
58 #include <gp_Trsf.hxx>
59 #include <gp_Vec.hxx>
60 #include <gp_XYZ.hxx>
61 #include <Precision.hxx>
62 #include <Standard_ConstructionError.hxx>
63 #include <Standard_NoSuchObject.hxx>
64 #include <Standard_NotImplemented.hxx>
65 #include <Standard_RangeError.hxx>
66 #include <Standard_Type.hxx>
67 #include <TColgp_Array1OfPnt.hxx>
68 #include <TColgp_Array2OfVec.hxx>
69 #include <TColgp_HArray2OfPnt.hxx>
70 #include <TColStd_Array1OfInteger.hxx>
71 #include <TColStd_Array1OfReal.hxx>
72 #include <TColStd_HArray1OfInteger.hxx>
73 #include <TColStd_HArray1OfReal.hxx>
74 #include <TColStd_HArray2OfInteger.hxx>
75
76 IMPLEMENT_STANDARD_RTTIEXT(Geom_OffsetSurface,Geom_Surface)
77
78 static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
79
80
81 //=======================================================================
82 //function : Copy
83 //purpose  : 
84 //=======================================================================
85
86 Handle(Geom_Geometry) Geom_OffsetSurface::Copy () const
87 {
88   Handle(Geom_OffsetSurface) S(new Geom_OffsetSurface(basisSurf, offsetValue, Standard_True));
89   return S;
90 }
91
92 //=======================================================================
93 //function : Geom_OffsetSurface
94 //purpose  : Basis surface cannot be an Offset surface or trimmed from
95 //            offset surface.
96 //=======================================================================
97
98 Geom_OffsetSurface::Geom_OffsetSurface (const Handle(Geom_Surface)& theSurf, 
99   const Standard_Real theOffset,
100   const Standard_Boolean isNotCheckC0) 
101   : offsetValue (theOffset) 
102 {
103   SetBasisSurface(theSurf, isNotCheckC0);
104 }
105
106 //=======================================================================
107 //function : SetBasisSurface
108 //purpose  : 
109 //=======================================================================
110
111 void Geom_OffsetSurface::SetBasisSurface (const Handle(Geom_Surface)& S,
112   const Standard_Boolean isNotCheckC0)
113 {
114   Standard_Real aUf, aUl, aVf, aVl;
115   S->Bounds(aUf, aUl, aVf, aVl);
116
117   Handle(Geom_Surface) aCheckingSurf = Handle(Geom_Surface)::DownCast(S->Copy());
118   Standard_Boolean isTrimmed = Standard_False;
119
120   while(aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
121         aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
122   {
123     if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
124     {
125       Handle(Geom_RectangularTrimmedSurface) aTrimS = 
126         Handle(Geom_RectangularTrimmedSurface)::DownCast(aCheckingSurf);
127       aCheckingSurf = aTrimS->BasisSurface();
128       isTrimmed = Standard_True;
129     }
130
131     if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
132     {
133       Handle(Geom_OffsetSurface) aOS = 
134         Handle(Geom_OffsetSurface)::DownCast(aCheckingSurf);
135       aCheckingSurf = aOS->BasisSurface();
136       offsetValue += aOS->Offset();
137     }
138   }
139
140   myBasisSurfContinuity = aCheckingSurf->Continuity();
141
142   Standard_Boolean isC0 = !isNotCheckC0 && (myBasisSurfContinuity == GeomAbs_C0);
143
144   // Basis surface must be at least C1
145   if (isC0)
146   {
147     Handle(Geom_Curve) aCurve;
148
149     if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)))
150     {
151       Handle(Geom_SurfaceOfRevolution) aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aCheckingSurf);
152       aCurve = aRevSurf->BasisCurve();
153     }
154     else if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)))
155     {
156       Handle(Geom_SurfaceOfLinearExtrusion) aLESurf = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aCheckingSurf);
157       aCurve = aLESurf->BasisCurve();
158     }
159
160     if(!aCurve.IsNull())
161     {
162       while(aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)) ||
163             aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
164       {
165         if (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
166         {
167           Handle(Geom_TrimmedCurve) aTrimC = 
168             Handle(Geom_TrimmedCurve)::DownCast(aCurve);
169           aCurve = aTrimC->BasisCurve();
170         }
171
172         if (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
173         {
174           Handle(Geom_OffsetCurve) aOC = 
175             Handle(Geom_OffsetCurve)::DownCast(aCurve);
176           aCurve = aOC->BasisCurve();
177         }
178       }
179     }
180
181     const Standard_Real aUIsoPar = (aUf + aUl)/2.0, aVIsoPar = (aVf + aVl)/2.0;
182     Standard_Boolean isUG1 = Standard_False, isVG1 = Standard_False;
183  
184     const Handle(Geom_Curve) aCurv1 = aCurve.IsNull() ? aCheckingSurf->UIso(aUIsoPar) : aCurve;
185     const Handle(Geom_Curve) aCurv2 = aCheckingSurf->VIso(aVIsoPar);
186     isUG1 = !aCurv1->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
187     isVG1 = !aCurv2->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
188
189     if(!isUG1)
190     {
191       Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv1);
192       isUG1 = aBC->IsG1(aVf, aVl, MyAngularToleranceForG1);
193     }
194     //
195     if(!isVG1)
196     {
197       Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv2);
198       isVG1 = aBC->IsG1(aUf, aUl, MyAngularToleranceForG1);
199     }
200     //
201     if(isUG1 && isVG1) 
202     {
203       myBasisSurfContinuity = GeomAbs_G1;
204       isC0 = Standard_False;
205     }
206
207     // Raise exception if still C0
208     if (isC0)
209       throw Standard_ConstructionError("Offset with no C1 Surface");
210   }
211
212   if(isTrimmed)
213   {
214     basisSurf = 
215       new Geom_RectangularTrimmedSurface(aCheckingSurf, aUf, aUl, aVf, aVl);
216   }
217   else
218   {
219     basisSurf = aCheckingSurf;
220   }
221   
222   equivSurf = Surface();
223
224   if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_BSplineSurface)) ||
225       aCheckingSurf->IsKind(STANDARD_TYPE(Geom_BezierSurface)))
226   {
227     // Tolerance en dur pour l'instant ,mais on devrait la proposer dans le constructeur
228     // et la mettre en champ, on pourrait utiliser par exemple pour l'extraction d'iso 
229     // et aussi pour les singularite. Pour les surfaces osculatrices, on l'utilise pour
230     // detecter si une iso est degeneree.
231     const Standard_Real Tol = Precision::Confusion(); //0.0001;
232     myOscSurf = new Geom_OsculatingSurface(aCheckingSurf, Tol);
233   }
234
235   // Surface value calculator
236   if (equivSurf.IsNull())
237     myEvaluator = new GeomEvaluator_OffsetSurface(basisSurf, offsetValue, myOscSurf);
238 }
239
240 //=======================================================================
241 //function : SetOffsetValue
242 //purpose  : 
243 //=======================================================================
244
245 void Geom_OffsetSurface::SetOffsetValue (const Standard_Real D)
246 {
247   offsetValue = D;
248   equivSurf = Surface();
249   if (equivSurf.IsNull())
250   {
251     if (myEvaluator.IsNull())
252       myEvaluator = new GeomEvaluator_OffsetSurface(basisSurf, offsetValue, myOscSurf);
253     else
254       myEvaluator->SetOffsetValue(offsetValue);
255   }
256 }
257
258 //=======================================================================
259 //function : UReverse
260 //purpose  : 
261 //=======================================================================
262
263 void Geom_OffsetSurface::UReverse ()
264 {
265   basisSurf->UReverse();
266   offsetValue = -offsetValue;
267   if (!equivSurf.IsNull())
268     equivSurf->UReverse();
269   else
270     myEvaluator->SetOffsetValue(offsetValue);
271 }
272
273 //=======================================================================
274 //function : UReversedParameter
275 //purpose  : 
276 //=======================================================================
277
278 Standard_Real Geom_OffsetSurface::UReversedParameter(const Standard_Real U) const
279 {
280   return basisSurf->UReversedParameter(U);
281 }
282
283 //=======================================================================
284 //function : VReverse
285 //purpose  : 
286 //=======================================================================
287
288 void Geom_OffsetSurface::VReverse ()
289 {
290   basisSurf->VReverse();
291   offsetValue = -offsetValue;
292   if (!equivSurf.IsNull())
293     equivSurf->VReverse();
294   else
295     myEvaluator->SetOffsetValue(offsetValue);
296 }
297
298 //=======================================================================
299 //function : VReversedParameter
300 //purpose  : 
301 //=======================================================================
302
303 Standard_Real Geom_OffsetSurface::VReversedParameter(const Standard_Real V) const
304 {
305   return basisSurf->VReversedParameter(V);
306 }
307
308 //=======================================================================
309 //function : Bounds
310 //purpose  : 
311 //=======================================================================
312
313 void Geom_OffsetSurface::Bounds (Standard_Real& U1, Standard_Real& U2, 
314                                  Standard_Real& V1, Standard_Real& V2) const
315 {
316   basisSurf->Bounds (U1, U2 ,V1, V2);
317 }
318
319 //=======================================================================
320 //function : Continuity
321 //purpose  : 
322 //=======================================================================
323
324 GeomAbs_Shape Geom_OffsetSurface::Continuity () const
325 {
326   switch (myBasisSurfContinuity) {
327     case GeomAbs_C2 : return GeomAbs_C1;
328     case GeomAbs_C3 : return GeomAbs_C2;
329     case GeomAbs_CN : return GeomAbs_CN;
330     default : break;
331   }
332   return GeomAbs_C0;
333 }
334
335 //=======================================================================
336 //function : D0
337 //purpose  : 
338 //=======================================================================
339
340 void Geom_OffsetSurface::D0 (const Standard_Real U, const Standard_Real V, gp_Pnt& P) const
341 {
342 #ifdef CHECK  
343   if (myBasisSurfContinuity == GeomAbs_C0)
344     throw Geom_UndefinedValue();
345 #endif
346   if (equivSurf.IsNull())
347     myEvaluator->D0(U, V, P);
348   else
349     equivSurf->D0(U,V,P);
350 }
351
352 //=======================================================================
353 //function : D1
354 //purpose  : 
355 //=======================================================================
356
357 void Geom_OffsetSurface::D1 (const Standard_Real U, const Standard_Real V, 
358   gp_Pnt& P, 
359   gp_Vec& D1U, gp_Vec& D1V) const 
360 {
361 #ifdef CHECK  
362   if (myBasisSurfContinuity == GeomAbs_C0 ||
363       myBasisSurfContinuity == GeomAbs_C1)
364     throw Geom_UndefinedDerivative();
365 #endif
366   if (equivSurf.IsNull())
367     myEvaluator->D1(U, V, P, D1U, D1V);
368   else
369     equivSurf->D1(U,V,P,D1U,D1V);
370 }
371
372 //=======================================================================
373 //function : D2
374 //purpose  : 
375 //=======================================================================
376
377 void Geom_OffsetSurface::D2 (const Standard_Real U, const Standard_Real V, 
378   gp_Pnt& P, 
379   gp_Vec& D1U, gp_Vec& D1V,
380   gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV) const
381 {
382 #ifdef CHECK  
383   if (myBasisSurfContinuity == GeomAbs_C0 ||
384       myBasisSurfContinuity == GeomAbs_C1 ||
385       myBasisSurfContinuity == GeomAbs_C2)
386     throw Geom_UndefinedDerivative();
387 #endif
388   if (equivSurf.IsNull())
389     myEvaluator->D2(U, V, P, D1U, D1V, D2U, D2V, D2UV);
390   else
391     equivSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
392 }
393
394 //=======================================================================
395 //function : D3
396 //purpose  : 
397 //=======================================================================
398
399 void Geom_OffsetSurface::D3 (const Standard_Real U, const Standard_Real V,
400   gp_Pnt& P, 
401   gp_Vec& D1U, gp_Vec& D1V, 
402   gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
403   gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
404 {
405 #ifdef CHECK  
406   if (!(basisSurf->IsCNu (4) && basisSurf->IsCNv (4))) { 
407     throw Geom_UndefinedDerivative();
408   }
409 #endif
410   if (equivSurf.IsNull())
411     myEvaluator->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
412   else
413     equivSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
414 }
415
416 //=======================================================================
417 //function : DN
418 //purpose  : 
419 //=======================================================================
420
421 gp_Vec Geom_OffsetSurface::DN (const Standard_Real    U, const Standard_Real    V,
422   const Standard_Integer Nu, const Standard_Integer Nv) const
423 {
424   Standard_RangeError_Raise_if (Nu < 0 || Nv < 0 || Nu + Nv < 1, " ");
425 #ifdef CHECK  
426   if (!(basisSurf->IsCNu (Nu) && basisSurf->IsCNv (Nv))) { 
427     throw Geom_UndefinedDerivative();
428   }
429 #endif  
430   gp_Vec D(0,0,0);
431
432   if (equivSurf.IsNull())
433     D = myEvaluator->DN(U, V, Nu, Nv);
434   else
435     D = equivSurf->DN(U,V,Nu,Nv);
436   return D; 
437 }
438
439
440 ////*************************************************
441 ////
442 ////   EVALUATOR FOR THE ISO-CURVE APPROXIMATION
443 ////
444 ////*************************************************
445
446 class Geom_OffsetSurface_UIsoEvaluator : public AdvApprox_EvaluatorFunction
447 {
448 public:
449   Geom_OffsetSurface_UIsoEvaluator (const Handle(Geom_Surface)& theSurface, const Standard_Real theU)
450     : CurrentSurface(theSurface), IsoPar(theU) {}
451
452   virtual void Evaluate (Standard_Integer *Dimension,
453     Standard_Real     StartEnd[2],
454     Standard_Real    *Parameter,
455     Standard_Integer *DerivativeRequest,
456     Standard_Real    *Result, // [Dimension]
457     Standard_Integer *ErrorCode);
458
459 private:
460   GeomAdaptor_Surface CurrentSurface;
461   Standard_Real IsoPar;
462 };
463
464 void Geom_OffsetSurface_UIsoEvaluator::Evaluate(Standard_Integer *,/*Dimension*/
465   Standard_Real     /*StartEnd*/[2],
466   Standard_Real    *Parameter,
467   Standard_Integer *DerivativeRequest,
468   Standard_Real    *Result,
469   Standard_Integer *ReturnCode) 
470
471   gp_Pnt P;
472   if (*DerivativeRequest == 0) {
473     P = CurrentSurface.Value(IsoPar,*Parameter);
474     Result[0] = P.X();
475     Result[1] = P.Y();
476     Result[2] = P.Z();
477   }
478   else {
479     gp_Vec DU,DV;
480     CurrentSurface.D1(IsoPar,*Parameter,P,DU,DV);
481     Result[0] = DV.X();
482     Result[1] = DV.Y();
483     Result[2] = DV.Z();
484   }
485   *ReturnCode = 0;
486 }
487
488 class Geom_OffsetSurface_VIsoEvaluator : public AdvApprox_EvaluatorFunction
489 {
490 public:
491   Geom_OffsetSurface_VIsoEvaluator (const Handle(Geom_Surface)& theSurface, const Standard_Real theV)
492     : CurrentSurface(theSurface), IsoPar(theV) {}
493
494   virtual void Evaluate (Standard_Integer *Dimension,
495     Standard_Real     StartEnd[2],
496     Standard_Real    *Parameter,
497     Standard_Integer *DerivativeRequest,
498     Standard_Real    *Result, // [Dimension]
499     Standard_Integer *ErrorCode);
500
501 private:
502   Handle(Geom_Surface) CurrentSurface;
503   Standard_Real IsoPar;
504 };
505
506 void Geom_OffsetSurface_VIsoEvaluator::Evaluate(Standard_Integer *,/*Dimension*/
507   Standard_Real     /*StartEnd*/[2],
508   Standard_Real    *Parameter,
509   Standard_Integer *DerivativeRequest,
510   Standard_Real    *Result,
511   Standard_Integer *ReturnCode) 
512
513   gp_Pnt P;
514   if (*DerivativeRequest == 0) {
515     P = CurrentSurface->Value(*Parameter,IsoPar);
516     Result[0] = P.X();
517     Result[1] = P.Y();
518     Result[2] = P.Z();
519   }
520   else {
521     gp_Vec DU,DV;
522     CurrentSurface->D1(*Parameter,IsoPar,P,DU,DV);
523     Result[0] = DU.X();
524     Result[1] = DU.Y();
525     Result[2] = DU.Z();
526   }
527   *ReturnCode = 0;
528 }
529
530 //=======================================================================
531 //function : UIso
532 //purpose  : The Uiso or the VIso of an OffsetSurface can't be clearly 
533 //           exprimed as a curve from Geom. So, to extract the U or VIso
534 //           an Approximation is needed. This approx always will return a 
535 //           BSplineCurve from Geom.
536 //=======================================================================
537
538 Handle(Geom_Curve) Geom_OffsetSurface::UIso (const Standard_Real UU) const 
539 {
540   if (equivSurf.IsNull()) {
541     const Standard_Integer Num1 = 0, Num2 = 0, Num3 = 1;
542     Handle(TColStd_HArray1OfReal) T1, T2, T3 = new TColStd_HArray1OfReal(1,Num3);
543     T3->Init(Precision::Approximation());
544     Standard_Real U1,U2,V1,V2;
545     Bounds(U1,U2,V1,V2);
546     const GeomAbs_Shape Cont = GeomAbs_C1;
547     const Standard_Integer MaxSeg = 100, MaxDeg = 14;
548
549     Handle(Geom_OffsetSurface) me (this);
550     Geom_OffsetSurface_UIsoEvaluator ev (me, UU);
551     AdvApprox_ApproxAFunction Approx(Num1, Num2, Num3, T1, T2, T3,
552       V1, V2, Cont, MaxDeg, MaxSeg, ev);
553
554     Standard_ConstructionError_Raise_if (!Approx.IsDone(), " Geom_OffsetSurface : UIso");
555
556     const Standard_Integer NbPoles = Approx.NbPoles();
557
558     TColgp_Array1OfPnt      Poles( 1, NbPoles);
559     TColStd_Array1OfReal    Knots( 1, Approx.NbKnots());
560     TColStd_Array1OfInteger Mults( 1, Approx.NbKnots());
561
562     Approx.Poles(1, Poles);
563     Knots = Approx.Knots()->Array1();
564     Mults = Approx.Multiplicities()->Array1();
565
566     Handle(Geom_BSplineCurve) C = 
567       new Geom_BSplineCurve( Poles, Knots, Mults, Approx.Degree());
568     return C;
569   }
570   else
571     return equivSurf->UIso(UU);
572 }
573
574 //=======================================================================
575 //function : VIso
576 //purpose  : 
577 //=======================================================================
578
579 Handle(Geom_Curve) Geom_OffsetSurface::VIso (const Standard_Real VV) const 
580 {
581   if (equivSurf.IsNull()) {
582     const Standard_Integer Num1 = 0, Num2 = 0, Num3 = 1;
583     Handle(TColStd_HArray1OfReal) T1, T2, T3 = new TColStd_HArray1OfReal(1,Num3);
584     T3->Init(Precision::Approximation());
585     Standard_Real U1,U2,V1,V2;
586     Bounds(U1,U2,V1,V2);
587     const GeomAbs_Shape Cont = GeomAbs_C1;
588     const Standard_Integer MaxSeg = 100, MaxDeg = 14;
589
590     Handle(Geom_OffsetSurface) me (this);
591     Geom_OffsetSurface_VIsoEvaluator ev (me, VV);
592     AdvApprox_ApproxAFunction Approx (Num1, Num2, Num3, T1, T2, T3,
593       U1, U2, Cont, MaxDeg, MaxSeg, ev);
594
595     Standard_ConstructionError_Raise_if (!Approx.IsDone(), " Geom_OffsetSurface : VIso");
596
597     TColgp_Array1OfPnt      Poles( 1, Approx.NbPoles());
598     TColStd_Array1OfReal    Knots( 1, Approx.NbKnots());
599     TColStd_Array1OfInteger Mults( 1, Approx.NbKnots());
600
601     Approx.Poles(1, Poles);
602     Knots = Approx.Knots()->Array1();
603     Mults = Approx.Multiplicities()->Array1();
604
605     Handle(Geom_BSplineCurve) C = 
606       new Geom_BSplineCurve( Poles, Knots, Mults, Approx.Degree());
607     return C;
608   }
609   else
610     return equivSurf->VIso(VV);
611 }
612
613 //=======================================================================
614 //function : IsCNu
615 //purpose  : 
616 //=======================================================================
617
618 Standard_Boolean Geom_OffsetSurface::IsCNu (const Standard_Integer N) const
619 {
620   Standard_RangeError_Raise_if (N < 0, " ");
621   return basisSurf->IsCNu (N+1);
622 }
623
624 //=======================================================================
625 //function : IsCNv
626 //purpose  : 
627 //=======================================================================
628
629 Standard_Boolean Geom_OffsetSurface::IsCNv (const Standard_Integer N) const
630 {
631   Standard_RangeError_Raise_if (N < 0, " ");
632   return basisSurf->IsCNv (N+1);
633 }
634
635 //=======================================================================
636 //function : IsUPeriodic
637 //purpose  : 
638 //=======================================================================
639
640 Standard_Boolean Geom_OffsetSurface::IsUPeriodic () const 
641 {
642   return basisSurf->IsUPeriodic();
643 }
644
645 //=======================================================================
646 //function : UPeriod
647 //purpose  : 
648 //=======================================================================
649
650 Standard_Real Geom_OffsetSurface::UPeriod() const
651 {
652   return basisSurf->UPeriod();
653 }
654
655 //=======================================================================
656 //function : IsVPeriodic
657 //purpose  : 
658 //=======================================================================
659
660 Standard_Boolean Geom_OffsetSurface::IsVPeriodic () const 
661 {
662   return basisSurf->IsVPeriodic();
663 }
664
665 //=======================================================================
666 //function : VPeriod
667 //purpose  : 
668 //=======================================================================
669
670 Standard_Real Geom_OffsetSurface::VPeriod() const
671 {
672   return basisSurf->VPeriod();
673 }
674
675 //=======================================================================
676 //function : IsUClosed
677 //purpose  : 
678 //=======================================================================
679
680 Standard_Boolean Geom_OffsetSurface::IsUClosed () const
681 {
682   Standard_Boolean UClosed;
683   Handle(Geom_Surface) SBasis = BasisSurface();
684
685   if (SBasis->IsKind (STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
686     Handle(Geom_RectangularTrimmedSurface) St = 
687       Handle(Geom_RectangularTrimmedSurface)::DownCast(SBasis);
688
689     Handle(Geom_Surface) S = St->BasisSurface();
690     if (S->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
691       UClosed = SBasis->IsUClosed();
692     }
693     else if (S->IsKind (STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) { 
694       Handle(Geom_SurfaceOfLinearExtrusion) Extru = 
695         Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S);
696
697       Handle(Geom_Curve) C = Extru->BasisCurve();
698       if (C->IsKind (STANDARD_TYPE(Geom_Circle)) || C->IsKind (STANDARD_TYPE(Geom_Ellipse))) {
699         UClosed = SBasis->IsUClosed();
700       }
701       else { UClosed = Standard_False; }
702     }
703     else if (S->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) { 
704       UClosed = SBasis->IsUClosed();
705     }
706     else { UClosed = Standard_False; }
707   }
708   else {
709     if (SBasis->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
710       UClosed = SBasis->IsUClosed();
711     }
712     else if (SBasis->IsKind (STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) { 
713       Handle(Geom_SurfaceOfLinearExtrusion) Extru = 
714         Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(SBasis);
715
716       Handle(Geom_Curve) C = Extru->BasisCurve();
717       UClosed = (C->IsKind(STANDARD_TYPE(Geom_Circle)) || C->IsKind(STANDARD_TYPE(Geom_Ellipse)));
718     }
719     else if (SBasis->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) { 
720       UClosed = Standard_True; 
721     }
722     else { UClosed = Standard_False; }
723   }  
724   return UClosed;
725 }
726
727 //=======================================================================
728 //function : IsVClosed
729 //purpose  : 
730 //=======================================================================
731
732 Standard_Boolean Geom_OffsetSurface::IsVClosed () const
733 {
734   Standard_Boolean VClosed;
735   Handle(Geom_Surface) SBasis = BasisSurface();
736
737   if (SBasis->IsKind (STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
738     Handle(Geom_RectangularTrimmedSurface) St = 
739       Handle(Geom_RectangularTrimmedSurface)::DownCast(SBasis);
740
741     Handle(Geom_Surface) S = St->BasisSurface();
742     if (S->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
743       VClosed = SBasis->IsVClosed();
744     }
745     else { VClosed = Standard_False; }
746   }
747   else {
748     if (SBasis->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
749       VClosed = SBasis->IsVClosed();
750     }
751     else { VClosed = Standard_False; }
752   }
753   return VClosed;
754 }
755
756 //=======================================================================
757 //function : Transform
758 //purpose  : 
759 //=======================================================================
760
761 void Geom_OffsetSurface::Transform (const gp_Trsf& T)
762 {
763   basisSurf->Transform (T);
764   offsetValue *= T.ScaleFactor();
765   equivSurf.Nullify();
766   if (myEvaluator.IsNull())
767     myEvaluator = new GeomEvaluator_OffsetSurface(basisSurf, offsetValue, myOscSurf);
768   else
769     myEvaluator->SetOffsetValue(offsetValue);
770 }
771
772 //=======================================================================
773 //function : TransformParameters
774 //purpose  : 
775 //=======================================================================
776
777 void Geom_OffsetSurface::TransformParameters(Standard_Real& U, Standard_Real& V,
778   const gp_Trsf& T) const
779 {
780   basisSurf->TransformParameters(U,V,T);
781   if(!equivSurf.IsNull()) equivSurf->TransformParameters(U,V,T);
782 }
783
784 //=======================================================================
785 //function : ParametricTransformation
786 //purpose  : 
787 //=======================================================================
788
789 gp_GTrsf2d Geom_OffsetSurface::ParametricTransformation (const gp_Trsf& T) const
790 {
791   return basisSurf->ParametricTransformation(T);
792 }
793
794 //=======================================================================
795 //function : Surface
796 //purpose  : Trouve si elle existe, une surface non offset, equivalente
797 //           a l'offset surface.
798 //=======================================================================
799
800 Handle(Geom_Surface) Geom_OffsetSurface::Surface() const 
801 {
802   if (offsetValue == 0.0) return  basisSurf; // Cas direct 
803
804   Standard_Real Tol = Precision::Confusion();
805   Handle(Geom_Surface) Result, Base;
806   Result.Nullify();
807   Handle(Standard_Type) TheType = basisSurf->DynamicType();
808   Standard_Boolean IsTrimmed;
809   Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
810
811   // Preambule pour les surface trimmes
812   if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
813     Handle(Geom_RectangularTrimmedSurface) S = 
814       Handle(Geom_RectangularTrimmedSurface)::DownCast(basisSurf);
815     Base = S->BasisSurface();
816     TheType = Base->DynamicType();
817     S->Bounds(U1,U2,V1,V2);  
818     IsTrimmed = Standard_True;
819   }
820   else {
821     IsTrimmed = Standard_False;
822     Base = basisSurf;
823   }
824
825   // Traite les surfaces cannonique
826   if (TheType == STANDARD_TYPE(Geom_Plane)) 
827   {
828     Handle(Geom_Plane) P =
829       Handle(Geom_Plane)::DownCast(Base);
830     gp_Vec T = P->Position().XDirection()^P->Position().YDirection();
831     T *= offsetValue;
832     Result = Handle(Geom_Plane)::DownCast(P->Translated(T));
833   }
834   else if (TheType == STANDARD_TYPE(Geom_CylindricalSurface)) 
835   {
836     Handle(Geom_CylindricalSurface) C =
837       Handle(Geom_CylindricalSurface)::DownCast(Base);
838     Standard_Real Radius = C->Radius();
839     gp_Ax3 Axis = C->Position();
840     if (Axis.Direct()) 
841       Radius += offsetValue;
842     else 
843       Radius -= offsetValue;
844     if ( Radius >= Tol ) {
845       Result = new Geom_CylindricalSurface( Axis, Radius);
846     }
847     else if ( Radius <= -Tol ){
848       Axis.Rotate(gp_Ax1(Axis.Location(),Axis.Direction()),M_PI);
849       Result = new Geom_CylindricalSurface( Axis, Abs(Radius));
850       Result->UReverse();
851     }
852     else 
853     {
854       // surface degeneree      
855     }
856   }
857   else if (TheType == STANDARD_TYPE(Geom_ConicalSurface)) 
858   {
859     Handle(Geom_ConicalSurface) C =
860       Handle(Geom_ConicalSurface)::DownCast(Base);
861     gp_Ax3 anAxis = C->Position();
862     Standard_Boolean isDirect = anAxis.Direct();
863     Standard_Real anAlpha = C->SemiAngle();
864     Standard_Real aRadius;
865     if (isDirect)
866     {
867       aRadius = C->RefRadius() + offsetValue * Cos (anAlpha);
868     }
869     else
870     {
871       aRadius = C->RefRadius() - offsetValue * Cos (anAlpha);
872     }
873     if (aRadius >= 0.)
874     {
875       gp_Vec aZ (anAxis.Direction());
876       if (isDirect)
877       {
878         aZ *= -offsetValue * Sin (anAlpha);
879       }
880       else
881       {
882         aZ *=  offsetValue * Sin (anAlpha);
883       }
884       anAxis.Translate (aZ);
885       Result = new Geom_ConicalSurface (anAxis, anAlpha, aRadius);
886     }
887     else
888     {
889       // surface degeneree      
890     }
891   }
892   else if (TheType == STANDARD_TYPE(Geom_SphericalSurface)) {
893     Handle(Geom_SphericalSurface) S = 
894       Handle(Geom_SphericalSurface)::DownCast(Base);
895     Standard_Real Radius = S->Radius();
896     gp_Ax3 Axis = S->Position();
897     if (Axis.Direct()) 
898       Radius += offsetValue;
899     else 
900       Radius -= offsetValue;
901     if ( Radius >= Tol) {
902       Result = new Geom_SphericalSurface(Axis, Radius);
903     }
904     else if ( Radius <= -Tol ) {
905       Axis.Rotate(gp_Ax1(Axis.Location(),Axis.Direction()),M_PI);
906       Axis.ZReverse();
907       Result = new Geom_SphericalSurface(Axis, -Radius);
908       Result->UReverse();
909     }
910     else {
911       //      surface degeneree
912     }
913   }
914   else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface)) 
915
916   {
917     Handle(Geom_ToroidalSurface) 
918       S = Handle(Geom_ToroidalSurface)::DownCast(Base);
919     Standard_Real MajorRadius = S->MajorRadius();
920     Standard_Real MinorRadius = S->MinorRadius();
921     gp_Ax3 Axis = S->Position();
922     if (MinorRadius <= MajorRadius) 
923     {  
924       if (Axis.Direct())
925         MinorRadius += offsetValue;
926       else 
927         MinorRadius -= offsetValue;
928       if (MinorRadius >= Tol) 
929         Result = new Geom_ToroidalSurface(Axis,MajorRadius,MinorRadius);
930       //      else if (MinorRadius <= -Tol) 
931       //        Result->UReverse();
932       else 
933       {
934         //      surface degeneree
935       }
936     }
937   }
938
939   // S'il le faut on trimme le resultat
940   if (IsTrimmed && !Result.IsNull()) {
941     Base = Result;
942     Result = new Geom_RectangularTrimmedSurface (Base, U1, U2, V1,V2);
943   }
944
945   return Result;
946 }
947
948 //=======================================================================
949 //function : UOsculatingSurface
950 //purpose  : 
951 //=======================================================================
952
953 Standard_Boolean Geom_OffsetSurface::UOsculatingSurface(const Standard_Real U, const Standard_Real V,
954   Standard_Boolean& t, Handle(Geom_BSplineSurface)& L) const
955 {
956   return !myOscSurf.IsNull() && myOscSurf->UOscSurf(U,V,t,L);
957 }
958
959 //=======================================================================
960 //function : VOsculatingSurface
961 //purpose  : 
962 //=======================================================================
963
964 Standard_Boolean Geom_OffsetSurface::VOsculatingSurface(const Standard_Real U, const Standard_Real V,
965   Standard_Boolean& t, Handle(Geom_BSplineSurface)& L) const
966 {
967   return !myOscSurf.IsNull() && myOscSurf->VOscSurf(U, V, t, L);
968 }
969
970 //=======================================================================
971 //function : DumpJson
972 //purpose  : 
973 //=======================================================================
974 void Geom_OffsetSurface::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
975 {
976   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
977
978   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Geom_Surface)
979
980   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, basisSurf.get())
981   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, equivSurf.get())
982
983   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, offsetValue)
984   OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myOscSurf.get())
985   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myBasisSurfContinuity)
986 }