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