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