0026443: Offset surface hangs up
[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>
52#include <gp.hxx>
53#include <gp_Dir.hxx>
54#include <gp_GTrsf2d.hxx>
55#include <gp_Pnt.hxx>
56#include <gp_Trsf.hxx>
57#include <gp_Vec.hxx>
58#include <gp_XYZ.hxx>
59#include <Precision.hxx>
60#include <Standard_ConstructionError.hxx>
61#include <Standard_NoSuchObject.hxx>
62#include <Standard_NotImplemented.hxx>
63#include <Standard_RangeError.hxx>
64#include <Standard_Type.hxx>
7fd59977 65#include <TColgp_Array1OfPnt.hxx>
66#include <TColgp_Array2OfVec.hxx>
42cf5bc1 67#include <TColgp_HArray2OfPnt.hxx>
7fd59977 68#include <TColStd_Array1OfInteger.hxx>
42cf5bc1 69#include <TColStd_Array1OfReal.hxx>
7fd59977 70#include <TColStd_HArray1OfInteger.hxx>
42cf5bc1 71#include <TColStd_HArray1OfReal.hxx>
7fd59977 72#include <TColStd_HArray2OfInteger.hxx>
7fd59977 73
3d58dc49 74static const Standard_Real MyAngularToleranceForG1 = Precision::Angular();
9f4cd8eb 75
7fd59977 76//=======================================================================
77//function : derivatives
78//purpose :
79//=======================================================================
80
81static void derivatives(Standard_Integer MaxOrder,
3d58dc49 82 Standard_Integer MinOrder,
83 const Standard_Real U,
84 const Standard_Real V,
85 const Handle(Geom_Surface)& basisSurf,
86 const Standard_Integer Nu,
87 const Standard_Integer Nv,
88 const Standard_Boolean AlongU,
89 const Standard_Boolean AlongV,
90 const Handle(Geom_BSplineSurface)& L,
91 TColgp_Array2OfVec& DerNUV,
92 TColgp_Array2OfVec& DerSurf)
7fd59977 93{
3d58dc49 94 Standard_Integer i,j;
95 gp_Pnt P;
96 gp_Vec DL1U, DL1V, DL2U , DL2V , DL2UV ,DL3U, DL3UUV, DL3UVV, DL3V;
7fd59977 97
3d58dc49 98 if (AlongU || AlongV)
99 {
100 MaxOrder=0;
101 TColgp_Array2OfVec DerSurfL(0,MaxOrder+Nu+1,0,MaxOrder+Nv+1);
102 switch (MinOrder)
103 {
104 case 1 :
105 L->D1(U, V, P, DL1U, DL1V);
106 DerSurfL.SetValue(1, 0, DL1U);
107 DerSurfL.SetValue(0, 1, DL1V);
108 break;
109 case 2 :
110 L->D2(U, V, P, DL1U, DL1V, DL2U , DL2V , DL2UV);
111 DerSurfL.SetValue(1, 0, DL1U);
112 DerSurfL.SetValue(0, 1, DL1V);
113 DerSurfL.SetValue(1, 1, DL2UV);
114 DerSurfL.SetValue(2, 0, DL2U);
115 DerSurfL.SetValue(0, 2, DL2V);
116 break;
117 case 3 :
118 L->D3(U, V, P, DL1U, DL1V, DL2U , DL2V , DL2UV ,DL3U, DL3V ,DL3UUV, DL3UVV);
119 DerSurfL.SetValue(1, 0, DL1U);
120 DerSurfL.SetValue(0, 1, DL1V);
121 DerSurfL.SetValue(1, 1, DL2UV);
122 DerSurfL.SetValue(2, 0, DL2U);
123 DerSurfL.SetValue(0, 2, DL2V);
124 DerSurfL.SetValue(3, 0, DL3U);
125 DerSurfL.SetValue(2, 1, DL3UUV);
126 DerSurfL.SetValue(1, 2, DL3UVV);
127 DerSurfL.SetValue(0, 3, DL3V);
128 break;
129 default:
130 break;
131 }
7fd59977 132
3d58dc49 133 if(Nu <= Nv)
134 {
135 for(i=0;i<=MaxOrder+1+Nu;i++)
136 for(j=i;j<=MaxOrder+Nv+1;j++)
137 if(i+j> MinOrder)
138 {
139 DerSurfL.SetValue(i,j,L->DN(U,V,i,j));
140 DerSurf.SetValue(i,j,basisSurf->DN(U,V,i,j));
141 if (i!=j && j <= Nu+1)
142 {
143 DerSurf.SetValue(j,i,basisSurf->DN(U,V,j,i));
144 DerSurfL.SetValue(j,i,L->DN(U,V,j,i));
145 }
146 }
147 }
148 else
149 {
150 for(j=0;j<=MaxOrder+1+Nv;j++)
151 for(i=j;i<=MaxOrder+Nu+1;i++)
152 if(i+j> MinOrder)
153 {
154 DerSurfL.SetValue(i,j,L->DN(U,V,i,j));
155 DerSurf.SetValue(i,j,basisSurf->DN(U,V,i,j));
156 if (i!=j && i <= Nv+1)
7fd59977 157 {
3d58dc49 158 DerSurf.SetValue(j,i,basisSurf->DN(U,V,j,i));
159 DerSurfL.SetValue(j,i,L->DN(U,V,j,i));
160 }
161 }
162 }
163 for(i=0;i<=MaxOrder+Nu;i++)
164 for(j=0;j<=MaxOrder+Nv;j++)
165 {
166 if (AlongU)
167 DerNUV.SetValue(i,j,CSLib::DNNUV(i,j,DerSurfL,DerSurf));
168 if (AlongV)
169 DerNUV.SetValue(i,j,CSLib::DNNUV(i,j,DerSurf,DerSurfL));
7fd59977 170 }
3d58dc49 171
172 }
173 else
174 {
175
176 for(i=0;i<=MaxOrder+Nu+1;i++)
177 for(j=i;j<=MaxOrder+Nv+1;j++)
178 if(i+j>MinOrder)
179 {
180
181 DerSurf.SetValue(i,j,basisSurf->DN(U,V,i,j));
182 if (i!=j) DerSurf.SetValue(j,i,basisSurf->DN(U,V,j,i));
183 }
184 for(i=0;i<=MaxOrder+Nu;i++)
185 for(j=0;j<=MaxOrder+Nv;j++)
186 {
187 DerNUV.SetValue(i,j,CSLib::DNNUV(i,j,DerSurf));
188 }
189 }
190
7fd59977 191}
3d58dc49 192
7fd59977 193//=======================================================================
194//function : Copy
195//purpose :
196//=======================================================================
197
9f4cd8eb 198Handle(Geom_Geometry) Geom_OffsetSurface::Copy () const
199{
200 Handle(Geom_OffsetSurface) S(new Geom_OffsetSurface(basisSurf, offsetValue, Standard_True));
3d58dc49 201 return S;
7fd59977 202}
203
7fd59977 204//=======================================================================
205//function : Geom_OffsetSurface
3d58dc49 206//purpose : Basis surface cannot be an Offset surface or trimmed from
207// offset surface.
7fd59977 208//=======================================================================
209
3d58dc49 210Geom_OffsetSurface::Geom_OffsetSurface (const Handle(Geom_Surface)& theSurf,
211 const Standard_Real theOffset,
9f4cd8eb 212 const Standard_Boolean isNotCheckC0)
3d58dc49 213 : offsetValue (theOffset)
7fd59977 214{
9f4cd8eb 215 SetBasisSurface(theSurf, isNotCheckC0);
3d58dc49 216}
7fd59977 217
218//=======================================================================
219//function : SetBasisSurface
220//purpose :
221//=======================================================================
222
c04c30b3 223void Geom_OffsetSurface::SetBasisSurface (const Handle(Geom_Surface)& S,
3d58dc49 224 const Standard_Boolean isNotCheckC0)
06be28a4 225{
3d58dc49 226 Standard_Real aUf, aUl, aVf, aVl;
227 S->Bounds(aUf, aUl, aVf, aVl);
228
c04c30b3 229 Handle(Geom_Surface) aCheckingSurf = Handle(Geom_Surface)::DownCast(S->Copy());
3d58dc49 230 Standard_Boolean isTrimmed = Standard_False;
231
232 while(aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)) ||
9f4cd8eb 233 aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
3d58dc49 234 {
235 if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
236 {
237 Handle(Geom_RectangularTrimmedSurface) aTrimS =
238 Handle(Geom_RectangularTrimmedSurface)::DownCast(aCheckingSurf);
239 aCheckingSurf = aTrimS->BasisSurface();
240 isTrimmed = Standard_True;
241 }
242
243 if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface)))
244 {
245 Handle(Geom_OffsetSurface) aOS =
246 Handle(Geom_OffsetSurface)::DownCast(aCheckingSurf);
247 aCheckingSurf = aOS->BasisSurface();
248 offsetValue += aOS->Offset();
249 }
250 }
251
3d58dc49 252 myBasisSurfContinuity = aCheckingSurf->Continuity();
253
9f4cd8eb 254 Standard_Boolean isC0 = !isNotCheckC0 && (myBasisSurfContinuity == GeomAbs_C0);
06be28a4
RL
255
256 // Basis surface must be at least C1
3d58dc49 257 if (isC0)
06be28a4 258 {
3d58dc49 259 Handle(Geom_Curve) aCurve;
260
261 if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)))
06be28a4 262 {
3d58dc49 263 Handle(Geom_SurfaceOfRevolution) aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(aCheckingSurf);
264 aCurve = aRevSurf->BasisCurve();
265 }
266 else if (aCheckingSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)))
267 {
268 Handle(Geom_SurfaceOfLinearExtrusion) aLESurf = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aCheckingSurf);
269 aCurve = aLESurf->BasisCurve();
270 }
271
272 if(!aCurve.IsNull())
273 {
274 while(aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)) ||
9f4cd8eb 275 aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
06be28a4 276 {
3d58dc49 277 if (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
278 {
279 Handle(Geom_TrimmedCurve) aTrimC =
280 Handle(Geom_TrimmedCurve)::DownCast(aCurve);
281 aCurve = aTrimC->BasisCurve();
282 }
283
284 if (aCurve->IsKind(STANDARD_TYPE(Geom_OffsetCurve)))
285 {
286 Handle(Geom_OffsetCurve) aOC =
287 Handle(Geom_OffsetCurve)::DownCast(aCurve);
288 aCurve = aOC->BasisCurve();
289 }
06be28a4
RL
290 }
291 }
292
9f4cd8eb 293 const Standard_Real aUIsoPar = (aUf + aUl)/2.0, aVIsoPar = (aVf + aVl)/2.0;
3d58dc49 294 Standard_Boolean isUG1 = Standard_False, isVG1 = Standard_False;
295
296 const Handle(Geom_Curve) aCurv1 = aCurve.IsNull() ? aCheckingSurf->UIso(aUIsoPar) : aCurve;
297 const Handle(Geom_Curve) aCurv2 = aCheckingSurf->VIso(aVIsoPar);
298 isUG1 = !aCurv1->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
299 isVG1 = !aCurv2->IsKind(STANDARD_TYPE(Geom_BSplineCurve));
300
301 if(!isUG1)
302 {
303 Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv1);
304 isUG1 = aBC->IsG1(aVf, aVl, MyAngularToleranceForG1);
305 }
306 //
307 if(!isVG1)
308 {
309 Handle(Geom_BSplineCurve) aBC = Handle(Geom_BSplineCurve)::DownCast(aCurv2);
310 isVG1 = aBC->IsG1(aUf, aUl, MyAngularToleranceForG1);
311 }
312 //
313 if(isUG1 && isVG1)
314 {
315 myBasisSurfContinuity = GeomAbs_G1;
316 isC0 = Standard_False;
317 }
318
06be28a4 319 // Raise exception if still C0
3d58dc49 320 if (isC0)
06be28a4
RL
321 Standard_ConstructionError::Raise("Offset with no C1 Surface");
322 }
7fd59977 323
3d58dc49 324 if(isTrimmed)
325 {
326 basisSurf =
327 new Geom_RectangularTrimmedSurface(aCheckingSurf, aUf, aUl, aVf, aVl);
328 }
329 else
330 {
331 basisSurf = aCheckingSurf;
332 }
333
7fd59977 334 equivSurf = Surface();
3d58dc49 335 //
336 // Tolerance en dur pour l'instant ,mais on devrait la proposer dans le constructeur
337 // et la mettre en champ, on pourrait utiliser par exemple pour l'extraction d'iso
338 // et aussi pour les singularite. Pour les surfaces osculatrices, on l'utilise pour
339 // detecter si une iso est degeneree.
9f4cd8eb 340 const Standard_Real Tol = Precision::Confusion(); //0.0001;
3d58dc49 341 myOscSurf.Init(basisSurf,Tol);
7fd59977 342}
343
7fd59977 344//=======================================================================
345//function : SetOffsetValue
346//purpose :
347//=======================================================================
348
9f4cd8eb 349void Geom_OffsetSurface::SetOffsetValue (const Standard_Real D)
350{
7fd59977 351 offsetValue = D;
352 equivSurf = Surface();
353}
354
355//=======================================================================
356//function : UReverse
357//purpose :
358//=======================================================================
359
9f4cd8eb 360void Geom_OffsetSurface::UReverse ()
361{
7fd59977 362 basisSurf->UReverse();
363 offsetValue = -offsetValue;
364 if(!equivSurf.IsNull()) equivSurf->UReverse();
365}
366
7fd59977 367//=======================================================================
368//function : UReversedParameter
369//purpose :
370//=======================================================================
371
9f4cd8eb 372Standard_Real Geom_OffsetSurface::UReversedParameter(const Standard_Real U) const
373{
374 return basisSurf->UReversedParameter(U);
7fd59977 375}
376
7fd59977 377//=======================================================================
378//function : VReverse
379//purpose :
380//=======================================================================
381
9f4cd8eb 382void Geom_OffsetSurface::VReverse ()
383{
7fd59977 384 basisSurf->VReverse();
385 offsetValue = -offsetValue;
386 if(!equivSurf.IsNull()) equivSurf->VReverse();
387}
388
7fd59977 389//=======================================================================
390//function : VReversedParameter
391//purpose :
392//=======================================================================
393
9f4cd8eb 394Standard_Real Geom_OffsetSurface::VReversedParameter(const Standard_Real V) const
7fd59977 395{
9f4cd8eb 396 return basisSurf->VReversedParameter(V);
7fd59977 397}
398
7fd59977 399//=======================================================================
400//function : Bounds
401//purpose :
402//=======================================================================
403
9f4cd8eb 404void Geom_OffsetSurface::Bounds (Standard_Real& U1, Standard_Real& U2,
405 Standard_Real& V1, Standard_Real& V2) const
406{
407 basisSurf->Bounds (U1, U2 ,V1, V2);
7fd59977 408}
409
7fd59977 410//=======================================================================
411//function : Continuity
412//purpose :
413//=======================================================================
414
9f4cd8eb 415GeomAbs_Shape Geom_OffsetSurface::Continuity () const
416{
3d58dc49 417 switch (myBasisSurfContinuity) {
9f4cd8eb 418 case GeomAbs_C2 : return GeomAbs_C1;
419 case GeomAbs_C3 : return GeomAbs_C2;
420 case GeomAbs_CN : return GeomAbs_CN;
421 default : break;
7fd59977 422 }
9f4cd8eb 423 return GeomAbs_C0;
7fd59977 424}
425
7fd59977 426//=======================================================================
427//function : D0
428//purpose :
429//=======================================================================
430
9f4cd8eb 431void Geom_OffsetSurface::D0 (const Standard_Real U, const Standard_Real V, gp_Pnt& P) const
432{
433 gp_Vec D1U, D1V;
7fd59977 434#ifdef CHECK
9f4cd8eb 435 if (myBasisSurfContinuity == GeomAbs_C0)
436 Geom_UndefinedValue::Raise();
7fd59977 437#endif
438 if (equivSurf.IsNull()){
439 basisSurf->D1(U, V, P, D1U, D1V);
440 SetD0(U,V,P,D1U,D1V);
441 }
9f4cd8eb 442 else
443 equivSurf->D0(U,V,P);
7fd59977 444}
445
7fd59977 446//=======================================================================
447//function : D1
448//purpose :
449//=======================================================================
450
451void Geom_OffsetSurface::D1 (const Standard_Real U, const Standard_Real V,
9f4cd8eb 452 gp_Pnt& P,
453 gp_Vec& D1U, gp_Vec& D1V) const
7fd59977 454{
7fd59977 455#ifdef CHECK
9f4cd8eb 456 if (myBasisSurfContinuity == GeomAbs_C0 ||
457 myBasisSurfContinuity == GeomAbs_C1)
458 Geom_UndefinedDerivative::Raise();
7fd59977 459#endif
460 if (equivSurf.IsNull())
461 {
462 gp_Vec d2u, d2v, d2uv;
9f4cd8eb 463 basisSurf->D2(U, V, P, D1U, D1V, d2u, d2v, d2uv);
464 SetD1(U,V,P,D1U,D1V,d2u,d2v,d2uv);
7fd59977 465 }
9f4cd8eb 466 else
7fd59977 467 equivSurf->D1(U,V,P,D1U,D1V);
7fd59977 468}
469
7fd59977 470//=======================================================================
471//function : D2
472//purpose :
473//=======================================================================
474
475void Geom_OffsetSurface::D2 (const Standard_Real U, const Standard_Real V,
9f4cd8eb 476 gp_Pnt& P,
477 gp_Vec& D1U, gp_Vec& D1V,
478 gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV) const
479{
7fd59977 480#ifdef CHECK
9f4cd8eb 481 if (myBasisSurfContinuity == GeomAbs_C0 ||
3d58dc49 482 myBasisSurfContinuity == GeomAbs_C1 ||
483 myBasisSurfContinuity == GeomAbs_C2)
9f4cd8eb 484 Geom_UndefinedDerivative::Raise();
7fd59977 485#endif
9f4cd8eb 486 if (equivSurf.IsNull())
487 {
488 gp_Vec d3u, d3uuv, d3uvv, d3v;
489 basisSurf->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, d3u, d3v, d3uuv, d3uvv);
490 SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,d3u,d3v,d3uuv,d3uvv);
491 }
492 else
493 equivSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
7fd59977 494}
495
7fd59977 496//=======================================================================
497//function : D3
498//purpose :
499//=======================================================================
500
9f4cd8eb 501void Geom_OffsetSurface::D3 (const Standard_Real U, const Standard_Real V,
502 gp_Pnt& P,
503 gp_Vec& D1U, gp_Vec& D1V,
504 gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
505 gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
506{
7fd59977 507#ifdef CHECK
9f4cd8eb 508 if (!(basisSurf->IsCNu (4) && basisSurf->IsCNv (4))) {
509 Geom_UndefinedDerivative::Raise();
510 }
7fd59977 511#endif
9f4cd8eb 512 if (equivSurf.IsNull())
513 {
514 basisSurf->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
515 SetD3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
516 }
517 else
518 equivSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 519}
3d58dc49 520
7fd59977 521//=======================================================================
522//function : DN
523//purpose :
524//=======================================================================
525
9f4cd8eb 526gp_Vec Geom_OffsetSurface::DN (const Standard_Real U, const Standard_Real V,
527 const Standard_Integer Nu, const Standard_Integer Nv) const
7fd59977 528{
7fd59977 529 Standard_RangeError_Raise_if (Nu < 0 || Nv < 0 || Nu + Nv < 1, " ");
530#ifdef CHECK
531 if (!(basisSurf->IsCNu (Nu) && basisSurf->IsCNv (Nv))) {
532 Geom_UndefinedDerivative::Raise();
533 }
534#endif
535 gp_Vec D(0,0,0);
536
537 if (equivSurf.IsNull())
538 {
9f4cd8eb 539 gp_Pnt P;
540 gp_Vec D1U,D1V;
3d58dc49 541 basisSurf->D1 (U, V, P, D1U, D1V);
7fd59977 542
3d58dc49 543 D = SetDN(U,V,Nu,Nv,D1U,D1V);
544 }
9f4cd8eb 545 else
546 D = equivSurf->DN(U,V,Nu,Nv);
7fd59977 547 return D;
548}
549
550//=======================================================================
551//function : D1
552//purpose :
553//=======================================================================
554
555void Geom_OffsetSurface::D1
556 (const Standard_Real U, const Standard_Real V,
9f4cd8eb 557 gp_Pnt& P, gp_Pnt& Pbasis,
558 gp_Vec& D1U, gp_Vec& D1V, gp_Vec& D1Ubasis, gp_Vec& D1Vbasis,
559 gp_Vec& D2Ubasis, gp_Vec& D2Vbasis, gp_Vec& D2UVbasis) const
560{
561 const GeomAbs_Shape basisCont = basisSurf->Continuity();
562 if (basisCont == GeomAbs_C0 || basisCont == GeomAbs_C1)
563 Geom_UndefinedDerivative::Raise();
564 basisSurf->D2 (U, V, Pbasis, D1Ubasis, D1Vbasis, D2Ubasis, D2Vbasis, D2UVbasis);
565 gp_Vec Ndir = D1Ubasis.Crossed (D1Vbasis);
566 const Standard_Real R2 = Ndir.SquareMagnitude();
567 const Standard_Real R = Sqrt (R2);
568 const Standard_Real R3 = R * R2;
569 gp_Vec DUNdir = D2Ubasis.Crossed (D1Vbasis);
570 DUNdir.Add (D1Ubasis.Crossed (D2UVbasis));
571 gp_Vec DVNdir = D2UVbasis.Crossed (D1Vbasis);
572 DVNdir.Add (D1Ubasis.Crossed (D2Vbasis));
573 const Standard_Real DRu = Ndir.Dot (DUNdir);
574 const Standard_Real DRv = Ndir.Dot (DVNdir);
575 if (R3 <= gp::Resolution()) {
576 if (R2 <= gp::Resolution())
577 Geom_UndefinedDerivative::Raise();
578 DUNdir.Multiply(R);
579 DUNdir.Subtract (Ndir.Multiplied (DRu/R));
580 DUNdir.Multiply (offsetValue/R2);
581 D1U = D1Ubasis.Added (DUNdir);
582 DVNdir.Multiply(R);
583 DVNdir.Subtract (Ndir.Multiplied (DRv/R));
584 DVNdir.Multiply (offsetValue/R2);
585 D1V = D1Vbasis.Added (DVNdir);
586 }
587 else {
588 DUNdir.Multiply (offsetValue / R);
589 DUNdir.Subtract (Ndir.Multiplied (offsetValue*DRu/R3));
590 D1U = D1Ubasis.Added (DUNdir);
591 DVNdir.Multiply (offsetValue / R);
592 DVNdir.Subtract (Ndir.Multiplied (offsetValue*DRv/R3));
593 D1V = D1Vbasis.Added (DVNdir);
594 }
595 Ndir.Multiply (offsetValue/R);
596 P.SetXYZ ((Ndir.XYZ()).Added (Pbasis.XYZ()));
7fd59977 597}
598
7fd59977 599//=======================================================================
600//function : D2
601//purpose :
602//=======================================================================
603
604void Geom_OffsetSurface::D2
605 (const Standard_Real U, const Standard_Real V,
9f4cd8eb 606 gp_Pnt& P, gp_Pnt& Pbasis,
607 gp_Vec& D1U, gp_Vec& D1V, gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
608 gp_Vec& D1Ubasis, gp_Vec& D1Vbasis,
609 gp_Vec& D2Ubasis, gp_Vec& D2Vbasis, gp_Vec& D2UVbasis,
610 gp_Vec& D3Ubasis, gp_Vec& D3Vbasis, gp_Vec& D3UUVbasis, gp_Vec& D3UVVbasis) const
611{
612 const GeomAbs_Shape basisCont = basisSurf->Continuity();
613 if (basisCont == GeomAbs_C0 || basisCont == GeomAbs_C1 || basisCont == GeomAbs_C2)
614 Geom_UndefinedDerivative::Raise();
615 basisSurf->D3 (U, V, P, D1Ubasis, D1Vbasis, D2Ubasis, D2Vbasis, D2UVbasis, D3Ubasis, D3Vbasis, D3UUVbasis, D3UVVbasis);
616 gp_Vec Ndir = D1Ubasis.Crossed (D1Vbasis);
617 const Standard_Real R2 = Ndir.SquareMagnitude();
618 const Standard_Real R = Sqrt (R2);
619 const Standard_Real R3 = R2 * R;
620 const Standard_Real R4 = R2 * R2;
621 const Standard_Real R5 = R3 * R2;
622 gp_Vec DUNdir = D2Ubasis.Crossed (D1Vbasis);
623 DUNdir.Add (D1Ubasis.Crossed (D2UVbasis));
624 gp_Vec DVNdir = D2UVbasis.Crossed (D1Vbasis);
625 DVNdir.Add (D1Ubasis.Crossed (D2Vbasis));
626 const Standard_Real DRu = Ndir.Dot (DUNdir);
627 const Standard_Real DRv = Ndir.Dot (DVNdir);
628 gp_Vec D2UNdir = D3Ubasis.Crossed (D1Vbasis);
629 D2UNdir.Add (D1Ubasis.Crossed (D3UUVbasis));
630 D2UNdir.Add (2.0 * (D2Ubasis.Crossed (D2UVbasis)));
631 gp_Vec D2VNdir = D3UVVbasis.Crossed (D1Vbasis);
632 D2VNdir.Add (D1Ubasis.Crossed (D3Vbasis));
633 D2VNdir.Add (2.0 * (D2UVbasis.Crossed (D2Vbasis)));
634 gp_Vec D2UVNdir = D2UVbasis.Crossed (D1Vbasis);
635 D2UVNdir.Add (D1Ubasis.Crossed (D3UVVbasis));
636 D2UVNdir.Add (D2Ubasis.Crossed (D2Vbasis));
637 const Standard_Real D2Ru = Ndir.Dot (D2UNdir) + DUNdir.Dot (DUNdir);
638 const Standard_Real D2Rv = Ndir.Dot (D2VNdir) + DVNdir.Dot (DVNdir);
639 const Standard_Real D2Ruv = DVNdir.Dot (DUNdir) + Ndir.Dot (D2UVNdir);
640
641 if (R5 <= gp::Resolution()) {
642 //We try another computation but the stability is not very good
643 //dixit ISG.
644 if (R4 <= gp::Resolution()) Geom_UndefinedDerivative::Raise();
645 // V2 = P" (U) :
646 // Standard_Real R4 = R2 * R2;
647 D2UNdir.Subtract (DUNdir.Multiplied (2.0 * DRu / R2));
648 D2UNdir.Subtract (Ndir.Multiplied (D2Ru/R2));
649 D2UNdir.Add (Ndir.Multiplied (3.0 * DRu * DRu / R4));
650 D2UNdir.Multiply (offsetValue / R);
651 D2U = D2Ubasis.Added (D2UNdir);
652 D2VNdir.Subtract (DVNdir.Multiplied (2.0 * DRv / R2));
653 D2VNdir.Subtract (Ndir.Multiplied (D2Rv/R2));
654 D2VNdir.Add (Ndir.Multiplied (3.0 * DRv * DRv / R4));
655 D2VNdir.Multiply (offsetValue / R);
656 D2V = D2Vbasis.Added (D2VNdir);
657
658 D2UVNdir.Subtract (DUNdir.Multiplied (DRv / R2));
659 D2UVNdir.Subtract (DVNdir.Multiplied (DRu / R2));
660 D2UVNdir.Subtract (Ndir.Multiplied (D2Ruv / R2));
661 D2UVNdir.Add (Ndir.Multiplied (3.0 * DRu * DRv / R4));
662 D2UVNdir.Multiply (offsetValue / R);
663 D2UV = D2UVbasis.Added (D2UVNdir);
664
665 DUNdir.Multiply(R);
666 DUNdir.Subtract (Ndir.Multiplied (DRu/R));
667 DUNdir.Multiply (offsetValue/R2);
668 D1U = D1Ubasis.Added (DUNdir);
669 DVNdir.Multiply(R);
670 DVNdir.Subtract (Ndir.Multiplied (DRv/R));
671 DVNdir.Multiply (offsetValue/R2);
672 D1V = D1Vbasis.Added (DVNdir);
673 }
674 else {
675 D2UNdir.Multiply (offsetValue/R);
676 D2UNdir.Subtract (DUNdir.Multiplied (2.0 * offsetValue * DRu / R3));
677 D2UNdir.Subtract (Ndir.Multiplied (offsetValue * D2Ru / R3));
678 D2UNdir.Add (Ndir.Multiplied (offsetValue * 3.0 * DRu * DRu / R5));
679 D2U = D2Ubasis.Added (D2UNdir);
680
681 D2VNdir.Multiply (offsetValue/R);
682 D2VNdir.Subtract (DVNdir.Multiplied (2.0 * offsetValue * DRv / R3));
683 D2VNdir.Subtract (Ndir.Multiplied (offsetValue * D2Rv / R3));
684 D2VNdir.Add (Ndir.Multiplied (offsetValue * 3.0 * DRv * DRv / R5));
685 D2V = D2Vbasis.Added (D2VNdir);
686
687 D2UVNdir.Multiply (offsetValue/R);
688 D2UVNdir.Subtract (DUNdir.Multiplied (offsetValue * DRv / R3));
689 D2UVNdir.Subtract (DVNdir.Multiplied (offsetValue * DRu / R3));
690 D2UVNdir.Subtract (Ndir.Multiplied (offsetValue * D2Ruv / R3));
691 D2UVNdir.Add (Ndir.Multiplied (3.0 * offsetValue * DRu * DRv / R5));
692 D2UV = D2UVbasis.Added (D2UVNdir);
693
694 DUNdir.Multiply (offsetValue / R);
695 DUNdir.Subtract (Ndir.Multiplied (offsetValue*DRu/R3));
696 D1U = D1Ubasis.Added (DUNdir);
697 DVNdir.Multiply (offsetValue / R);
698 DVNdir.Subtract (Ndir.Multiplied (offsetValue*DRv/R3));
699 D1V = D1Vbasis.Added (DVNdir);
700 }
701 Ndir.Multiply (offsetValue/R);
702 P.SetXYZ ((Ndir.XYZ()).Added (Pbasis.XYZ()));
7fd59977 703}
704
705//=======================================================================
706//function : LocalD0
707//purpose :
708//=======================================================================
709
9f4cd8eb 710void Geom_OffsetSurface::LocalD0 (const Standard_Real U, const Standard_Real V,
711 const Standard_Integer USide, const Standard_Integer VSide,
712 gp_Pnt& P) const
7fd59977 713{
714 if (equivSurf.IsNull()) {
9f4cd8eb 715 gp_Vec D1U, D1V;
7fd59977 716 Handle(Geom_Surface) Basis = basisSurf;
717
718 // if Basis is Trimmed we take the basis's basis
9f4cd8eb 719 Handle(Geom_RectangularTrimmedSurface) RTS =
720 Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
721 if (!RTS.IsNull())
7fd59977 722 Basis = RTS->BasisSurface();
3d58dc49 723
7fd59977 724 // BSpline case
9f4cd8eb 725 Handle(Geom_BSplineSurface) BSplS =
726 Handle(Geom_BSplineSurface)::DownCast(Basis);
7fd59977 727 if (!BSplS.IsNull()) {
9f4cd8eb 728 gp_Vec D2U,D2V,D2UV, D3U,D3V,D3UUV,D3UVV;
729 LocateSides(U,V,USide,VSide,BSplS,1,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 730 SetD0(U,V,P,D1U,D1V);
731 return;
732 }
733
734 // Extrusion case
9f4cd8eb 735 Handle( Geom_SurfaceOfLinearExtrusion) SE =
736 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
7fd59977 737 if (!SE.IsNull()) {
738 SE->LocalD1(U,V,USide,P,D1U,D1V);
739 SetD0(U,V,P,D1U,D1V);
740 return;
741 }
742
743 // Revolution case
9f4cd8eb 744 Handle(Geom_SurfaceOfRevolution) SR =
745 Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
7fd59977 746 if (!SR.IsNull()) {
9f4cd8eb 747 SR->LocalD1(U,V,VSide,P,D1U,D1V);
748 SetD0(U,V,P,D1U,D1V);
7fd59977 749 return;
750 }
3d58dc49 751
7fd59977 752 // General cases
753 basisSurf->D1(U, V, P, D1U, D1V);
9f4cd8eb 754 SetD0(U,V,P,D1U,D1V);
7fd59977 755 }
756 else
757 equivSurf-> D0(U,V,P);
758}
759
760//=======================================================================
761//function : LocalD1
762//purpose :
763//=======================================================================
764
9f4cd8eb 765void Geom_OffsetSurface::LocalD1 (const Standard_Real U, const Standard_Real V,
766 const Standard_Integer USide, const Standard_Integer VSide,
767 gp_Pnt& P,
768 gp_Vec& D1U, gp_Vec& D1V) const
7fd59977 769{
770 if (equivSurf.IsNull()) {
9f4cd8eb 771 gp_Vec D2U,D2V,D2UV ;
7fd59977 772 Handle(Geom_Surface) Basis = basisSurf;
773
774 // if Basis is Trimmed we take the basis's basis
9f4cd8eb 775 Handle(Geom_RectangularTrimmedSurface) RTS =
776 Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
777 if (!RTS.IsNull())
7fd59977 778 Basis = RTS->BasisSurface();
3d58dc49 779
7fd59977 780 // BSpline case
9f4cd8eb 781 Handle(Geom_BSplineSurface) BSplS =
782 Handle(Geom_BSplineSurface)::DownCast(Basis);
7fd59977 783 if (!BSplS.IsNull()) {
9f4cd8eb 784 gp_Vec D3U,D3V,D3UUV,D3UVV;
785 LocateSides(U,V,USide,VSide,BSplS,2,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 786 SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
787 return;
788 }
789
790 // Extrusion case
9f4cd8eb 791 Handle( Geom_SurfaceOfLinearExtrusion) SE =
792 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
7fd59977 793 if (!SE.IsNull()) {
794 SE->LocalD2(U,V,USide,P,D1U,D1V,D2U,D2V,D2UV);
795 SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
796 return;
797 }
798
799 // Revolution case
9f4cd8eb 800 Handle(Geom_SurfaceOfRevolution) SR =
801 Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
7fd59977 802 if (!SR.IsNull()) {
9f4cd8eb 803 SR->LocalD2(U,V,VSide,P,D1U,D1V,D2U,D2V,D2UV);
804 SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
7fd59977 805 return;
806 }
3d58dc49 807
7fd59977 808 // General cases
9f4cd8eb 809 basisSurf->D2(U, V, P, D1U, D1V, D2U, D2V, D2UV);
810 SetD1(U,V,P,D1U,D1V,D2U,D2V,D2UV);
7fd59977 811 }
812 else
9f4cd8eb 813 equivSurf->D1(U,V,P,D1U,D1V);
7fd59977 814}
815
816//=======================================================================
817//function : LocalD2
818//purpose :
819//=======================================================================
820
9f4cd8eb 821void Geom_OffsetSurface::LocalD2 (const Standard_Real U, const Standard_Real V,
822 const Standard_Integer USide, const Standard_Integer VSide,
823 gp_Pnt& P,
824 gp_Vec& D1U, gp_Vec& D1V,
825 gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV) const
7fd59977 826{
827 if (equivSurf.IsNull()) {
828 Handle(Geom_Surface) Basis = basisSurf;
9f4cd8eb 829 gp_Vec D3U,D3V,D3UUV,D3UVV;
7fd59977 830
831 // if Basis is Trimmed we take the basis's basis
9f4cd8eb 832 Handle(Geom_RectangularTrimmedSurface) RTS =
833 Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
834 if (!RTS.IsNull())
7fd59977 835 Basis = RTS->BasisSurface();
3d58dc49 836
7fd59977 837 // BSpline case
9f4cd8eb 838 Handle(Geom_BSplineSurface) BSplS =
839 Handle(Geom_BSplineSurface)::DownCast(Basis);
7fd59977 840 if (!BSplS.IsNull()) {
9f4cd8eb 841 LocateSides(U,V,USide,VSide,BSplS,3,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 842 SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
843 return;
844 }
845
9f4cd8eb 846 // Extrusion case
847 Handle(Geom_SurfaceOfLinearExtrusion) SE =
848 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
7fd59977 849 if (!SE.IsNull()) {
9f4cd8eb 850 SE->LocalD3(U,V,USide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 851 SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
852 return;
853 }
854
855 // Revolution case
9f4cd8eb 856 Handle(Geom_SurfaceOfRevolution) SR =
857 Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
7fd59977 858 if (!SR.IsNull()) {
9f4cd8eb 859 SR->LocalD3(U,V,VSide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
860 SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 861 return;
862 }
3d58dc49 863
7fd59977 864 // General cases
9f4cd8eb 865 basisSurf->D3(U, V, P, D1U, D1V, D2U, D2V, D2UV, D3U, D3V, D3UUV, D3UVV);
866 SetD2(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 867 }
868 else
9f4cd8eb 869 equivSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
7fd59977 870}
9f4cd8eb 871
7fd59977 872//=======================================================================
873//function : LocalD3
874//purpose :
875//=======================================================================
876
9f4cd8eb 877void Geom_OffsetSurface::LocalD3 (const Standard_Real U, const Standard_Real V,
878 const Standard_Integer USide, const Standard_Integer VSide,
879 gp_Pnt& P,
880 gp_Vec& D1U, gp_Vec& D1V,
881 gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
882 gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
7fd59977 883{
884 if (equivSurf.IsNull()) {
885 Handle(Geom_Surface) Basis = basisSurf;
886
887 // if Basis is Trimmed we take the basis's basis
9f4cd8eb 888 Handle(Geom_RectangularTrimmedSurface) RTS =
889 Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
890 if (!RTS.IsNull())
7fd59977 891 Basis = RTS->BasisSurface();
3d58dc49 892
7fd59977 893 // BSpline case
9f4cd8eb 894 Handle(Geom_BSplineSurface) BSplS =
895 Handle(Geom_BSplineSurface)::DownCast(Basis);
7fd59977 896 if (!BSplS.IsNull()) {
9f4cd8eb 897 LocateSides(U,V,USide,VSide,BSplS,3,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 898 SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
899 return;
900 }
901
902 // Extrusion case
9f4cd8eb 903 Handle(Geom_SurfaceOfLinearExtrusion) SE =
904 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
7fd59977 905 if (!SE.IsNull()) {
9f4cd8eb 906 SE->LocalD3(U,V,USide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 907 SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
908 return;
909 }
910
911 // Revolution case
9f4cd8eb 912 Handle(Geom_SurfaceOfRevolution) SR =
913 Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
7fd59977 914 if (!SR.IsNull()) {
9f4cd8eb 915 SR->LocalD3(U,V,VSide,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
916 SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 917 return;
918 }
3d58dc49 919
7fd59977 920 // General cases
9f4cd8eb 921 basisSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
922 SetD3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 923 }
924 else
9f4cd8eb 925 equivSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
7fd59977 926}
927
928//=======================================================================
929//function : LocalDN
930//purpose :
931//=======================================================================
932
9f4cd8eb 933gp_Vec Geom_OffsetSurface::LocalDN (const Standard_Real U, const Standard_Real V,
934 const Standard_Integer USide, const Standard_Integer VSide,
935 const Standard_Integer Nu, const Standard_Integer Nv) const
7fd59977 936{
7fd59977 937 if(equivSurf.IsNull()) {
938
9f4cd8eb 939 gp_Vec D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV;
940 gp_Pnt P;
7fd59977 941 Handle(Geom_Surface) Basis = basisSurf;
3d58dc49 942
9f4cd8eb 943 // if Basis is Trimmed we make the basis`s basis
944 Handle(Geom_RectangularTrimmedSurface) RTS =
945 Handle(Geom_RectangularTrimmedSurface)::DownCast(Basis);
946 if (!RTS.IsNull())
7fd59977 947 Basis = RTS -> BasisSurface();
3d58dc49 948
7fd59977 949 //BSpline case
9f4cd8eb 950 Handle(Geom_BSplineSurface) BSplS =
951 Handle(Geom_BSplineSurface)::DownCast(Basis);
7fd59977 952 if(!BSplS.IsNull()) {
953 LocateSides(U,V,USide,VSide,BSplS,1,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
9f4cd8eb 954 return SetDN(U,V,Nu,Nv,D1U,D1V);
7fd59977 955 }
3d58dc49 956
7fd59977 957 //Extrusion case
9f4cd8eb 958 Handle( Geom_SurfaceOfLinearExtrusion) SE =
959 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(Basis);
7fd59977 960 if(!SE.IsNull()) {
7fd59977 961 SE->LocalD1(U,V,USide,P,D1U,D1V);
9f4cd8eb 962 return SetDN(U,V,Nu,Nv,D1U,D1V);
7fd59977 963 }
3d58dc49 964
7fd59977 965 //Revolution case
9f4cd8eb 966 Handle(Geom_SurfaceOfRevolution) SR =
967 Handle(Geom_SurfaceOfRevolution)::DownCast(Basis);
7fd59977 968 if(!SR.IsNull()) {
9f4cd8eb 969 SR->LocalDN(U,V,VSide,Nu,Nv);
970 return SetDN(U,V,Nu,Nv,D1U,D1V);
7fd59977 971 }
3d58dc49 972
7fd59977 973 //General cases
9f4cd8eb 974 basisSurf->DN(U,V,Nu,Nv);
975 return SetDN(U,V,Nu,Nv,D1U,D1V);
7fd59977 976 }
977 else
9f4cd8eb 978 return equivSurf->DN(U,V,Nu,Nv);
7fd59977 979}
980
981//=======================================================================
982//function : LocateSides
983//purpose :
984//=======================================================================
9f4cd8eb 985
986void Geom_OffsetSurface::LocateSides(const Standard_Real U, const Standard_Real V,
987 const Standard_Integer USide, const Standard_Integer VSide,
3d58dc49 988 const Handle(Geom_BSplineSurface)& BSplS,
989 const Standard_Integer NDir,
990 gp_Pnt& P,
991 gp_Vec& D1U,gp_Vec& D1V,
992 gp_Vec& D2U,gp_Vec& D2V,gp_Vec& D2UV,
9f4cd8eb 993 gp_Vec& D3U,gp_Vec& D3V,gp_Vec& D3UUV,gp_Vec& D3UVV) const
7fd59977 994{
9f4cd8eb 995 Standard_Boolean UIsKnot=Standard_False, VIsKnot=Standard_False;
7fd59977 996 Standard_Integer Ideb, Ifin, IVdeb, IVfin;
9f4cd8eb 997 const Standard_Real ParTol=Precision::PConfusion()/10.;
7fd59977 998 BSplS->Geom_BSplineSurface::LocateU(U,ParTol,Ideb, Ifin, Standard_False);
999 BSplS->Geom_BSplineSurface::LocateV(V,ParTol,IVdeb,IVfin,Standard_False);
3d58dc49 1000
7fd59977 1001 if(Ideb == Ifin ) { //knot
1002
1003 if(USide == 1) {Ifin++; UIsKnot=Standard_True;}
7fd59977 1004 else if(USide == -1) {Ideb--; UIsKnot=Standard_True;}
7fd59977 1005 else {Ideb--; Ifin++;} //USide == 0
1006
1007 }
1008
1009 if(Ideb < BSplS->FirstUKnotIndex()) {Ideb = BSplS->FirstUKnotIndex(); Ifin = Ideb + 1;}
1010
1011 if(Ifin > BSplS->LastUKnotIndex()) {Ifin = BSplS->LastUKnotIndex(); Ideb = Ifin - 1;}
1012
7fd59977 1013 if(IVdeb == IVfin ) { //knot
1014
1015 if(VSide == 1) {IVfin++; VIsKnot=Standard_True;}
7fd59977 1016 else if(VSide == -1) {IVdeb--; VIsKnot=Standard_True;}
7fd59977 1017 else {IVdeb--; IVfin++;} //VSide == 0
1018
1019 }
1020
1021 if(IVdeb < BSplS->FirstVKnotIndex()) {IVdeb = BSplS->FirstVKnotIndex(); IVfin = IVdeb + 1;}
1022
1023 if(IVfin > BSplS->LastVKnotIndex()) {IVfin = BSplS->LastVKnotIndex(); IVdeb = IVfin - 1;}
1024
7fd59977 1025 if((UIsKnot)||(VIsKnot))
1026 switch(NDir)
9f4cd8eb 1027 {
1028 case 0 : BSplS->Geom_BSplineSurface::LocalD0(U,V,Ideb,Ifin,IVdeb,IVfin,P); break;
1029 case 1 : BSplS->Geom_BSplineSurface::LocalD1(U,V,Ideb,Ifin,IVdeb,IVfin,P,D1U,D1V); break;
1030 case 2 : BSplS->Geom_BSplineSurface::LocalD2(U,V,Ideb,Ifin,IVdeb,IVfin,P,D1U,D1V,D2U,D2V,D2UV); break;
1031 case 3 : BSplS->Geom_BSplineSurface::LocalD3(U,V,Ideb,Ifin,IVdeb,IVfin,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); break;
1032 }
1033 else
1034 switch(NDir)
1035 {
1036 case 0 : basisSurf->D0(U,V,P); break;
1037 case 1 : basisSurf->D1(U,V,P,D1U,D1V); break;
1038 case 2 : basisSurf->D2(U,V,P,D1U,D1V,D2U,D2V,D2UV); break;
1039 case 3 : basisSurf->D3(U,V,P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV); break;
1040 }
7fd59977 1041}
1042
7fd59977 1043////*************************************************
1044////
1045//// EVALUATOR FOR THE ISO-CURVE APPROXIMATION
1046////
1047////*************************************************
1048
1049class Geom_OffsetSurface_UIsoEvaluator : public AdvApprox_EvaluatorFunction
1050{
3d58dc49 1051public:
9f4cd8eb 1052 Geom_OffsetSurface_UIsoEvaluator (const Handle(Geom_Surface)& theSurface, const Standard_Real theU)
3d58dc49 1053 : CurrentSurface(theSurface), IsoPar(theU) {}
1054
7fd59977 1055 virtual void Evaluate (Standard_Integer *Dimension,
3d58dc49 1056 Standard_Real StartEnd[2],
1057 Standard_Real *Parameter,
1058 Standard_Integer *DerivativeRequest,
1059 Standard_Real *Result, // [Dimension]
1060 Standard_Integer *ErrorCode);
1061
1062private:
7fd59977 1063 Handle(Geom_Surface) CurrentSurface;
1064 Standard_Real IsoPar;
1065};
1066
1067void Geom_OffsetSurface_UIsoEvaluator::Evaluate(Standard_Integer *,/*Dimension*/
3d58dc49 1068 Standard_Real /*StartEnd*/[2],
1069 Standard_Real *Parameter,
1070 Standard_Integer *DerivativeRequest,
1071 Standard_Real *Result,
1072 Standard_Integer *ReturnCode)
7fd59977 1073{
1074 gp_Pnt P;
1075 if (*DerivativeRequest == 0) {
1076 P = CurrentSurface->Value(IsoPar,*Parameter);
9f4cd8eb 1077 Result[0] = P.X();
1078 Result[1] = P.Y();
1079 Result[2] = P.Z();
7fd59977 1080 }
1081 else {
1082 gp_Vec DU,DV;
1083 CurrentSurface->D1(IsoPar,*Parameter,P,DU,DV);
9f4cd8eb 1084 Result[0] = DV.X();
1085 Result[1] = DV.Y();
1086 Result[2] = DV.Z();
7fd59977 1087 }
9f4cd8eb 1088 *ReturnCode = 0;
7fd59977 1089}
1090
1091class Geom_OffsetSurface_VIsoEvaluator : public AdvApprox_EvaluatorFunction
1092{
3d58dc49 1093public:
9f4cd8eb 1094 Geom_OffsetSurface_VIsoEvaluator (const Handle(Geom_Surface)& theSurface, const Standard_Real theV)
3d58dc49 1095 : CurrentSurface(theSurface), IsoPar(theV) {}
1096
7fd59977 1097 virtual void Evaluate (Standard_Integer *Dimension,
3d58dc49 1098 Standard_Real StartEnd[2],
1099 Standard_Real *Parameter,
1100 Standard_Integer *DerivativeRequest,
1101 Standard_Real *Result, // [Dimension]
1102 Standard_Integer *ErrorCode);
1103
1104private:
7fd59977 1105 Handle(Geom_Surface) CurrentSurface;
1106 Standard_Real IsoPar;
1107};
1108
1109void Geom_OffsetSurface_VIsoEvaluator::Evaluate(Standard_Integer *,/*Dimension*/
3d58dc49 1110 Standard_Real /*StartEnd*/[2],
1111 Standard_Real *Parameter,
1112 Standard_Integer *DerivativeRequest,
1113 Standard_Real *Result,
1114 Standard_Integer *ReturnCode)
7fd59977 1115{
1116 gp_Pnt P;
1117 if (*DerivativeRequest == 0) {
1118 P = CurrentSurface->Value(*Parameter,IsoPar);
9f4cd8eb 1119 Result[0] = P.X();
1120 Result[1] = P.Y();
1121 Result[2] = P.Z();
7fd59977 1122 }
1123 else {
1124 gp_Vec DU,DV;
1125 CurrentSurface->D1(*Parameter,IsoPar,P,DU,DV);
9f4cd8eb 1126 Result[0] = DU.X();
1127 Result[1] = DU.Y();
1128 Result[2] = DU.Z();
7fd59977 1129 }
9f4cd8eb 1130 *ReturnCode = 0;
7fd59977 1131}
1132
1133//=======================================================================
1134//function : UIso
1135//purpose : The Uiso or the VIso of an OffsetSurface can't be clearly
1136// exprimed as a curve from Geom. So, to extract the U or VIso
1137// an Approximation is needed. This approx always will return a
1138// BSplineCurve from Geom.
1139//=======================================================================
1140
1141Handle(Geom_Curve) Geom_OffsetSurface::UIso (const Standard_Real UU) const
1142{
1143 if (equivSurf.IsNull()) {
9f4cd8eb 1144 const Standard_Integer Num1 = 0, Num2 = 0, Num3 = 1;
1145 Handle(TColStd_HArray1OfReal) T1, T2, T3 = new TColStd_HArray1OfReal(1,Num3);
7fd59977 1146 T3->Init(Precision::Approximation());
1147 Standard_Real U1,U2,V1,V2;
1148 Bounds(U1,U2,V1,V2);
9f4cd8eb 1149 const GeomAbs_Shape Cont = GeomAbs_C1;
1150 const Standard_Integer MaxSeg = 100, MaxDeg = 14;
7fd59977 1151
c04c30b3 1152 Handle(Geom_OffsetSurface) me (this);
1153 Geom_OffsetSurface_UIsoEvaluator ev (me, UU);
7fd59977 1154 AdvApprox_ApproxAFunction Approx(Num1, Num2, Num3, T1, T2, T3,
9f4cd8eb 1155 V1, V2, Cont, MaxDeg, MaxSeg, ev);
7fd59977 1156
9f4cd8eb 1157 Standard_ConstructionError_Raise_if (!Approx.IsDone(), " Geom_OffsetSurface : UIso");
7fd59977 1158
9f4cd8eb 1159 const Standard_Integer NbPoles = Approx.NbPoles();
7fd59977 1160
1161 TColgp_Array1OfPnt Poles( 1, NbPoles);
1162 TColStd_Array1OfReal Knots( 1, Approx.NbKnots());
1163 TColStd_Array1OfInteger Mults( 1, Approx.NbKnots());
1164
1165 Approx.Poles(1, Poles);
1166 Knots = Approx.Knots()->Array1();
1167 Mults = Approx.Multiplicities()->Array1();
1168
1169 Handle(Geom_BSplineCurve) C =
1170 new Geom_BSplineCurve( Poles, Knots, Mults, Approx.Degree());
1171 return C;
1172 }
1173 else
1174 return equivSurf->UIso(UU);
1175}
1176
7fd59977 1177//=======================================================================
1178//function : Value
1179//purpose :
1180//=======================================================================
1181
1182void Geom_OffsetSurface::Value
9f4cd8eb 1183 (const Standard_Real U, const Standard_Real V,
1184 gp_Pnt& P, gp_Pnt& ,
1185 gp_Vec& D1Ubasis, gp_Vec& D1Vbasis) const
1186{
1187 if (myBasisSurfContinuity == GeomAbs_C0)
1188 Geom_UndefinedValue::Raise();
3d58dc49 1189
9f4cd8eb 1190 SetD0(U,V,P,D1Ubasis,D1Vbasis);
7fd59977 1191}
1192
7fd59977 1193//=======================================================================
1194//function : VIso
1195//purpose :
1196//=======================================================================
1197
1198Handle(Geom_Curve) Geom_OffsetSurface::VIso (const Standard_Real VV) const
1199{
1200 if (equivSurf.IsNull()) {
9f4cd8eb 1201 const Standard_Integer Num1 = 0, Num2 = 0, Num3 = 1;
1202 Handle(TColStd_HArray1OfReal) T1, T2, T3 = new TColStd_HArray1OfReal(1,Num3);
7fd59977 1203 T3->Init(Precision::Approximation());
1204 Standard_Real U1,U2,V1,V2;
1205 Bounds(U1,U2,V1,V2);
9f4cd8eb 1206 const GeomAbs_Shape Cont = GeomAbs_C1;
1207 const Standard_Integer MaxSeg = 100, MaxDeg = 14;
7fd59977 1208
c04c30b3 1209 Handle(Geom_OffsetSurface) me (this);
1210 Geom_OffsetSurface_VIsoEvaluator ev (me, VV);
7fd59977 1211 AdvApprox_ApproxAFunction Approx (Num1, Num2, Num3, T1, T2, T3,
3d58dc49 1212 U1, U2, Cont, MaxDeg, MaxSeg, ev);
7fd59977 1213
9f4cd8eb 1214 Standard_ConstructionError_Raise_if (!Approx.IsDone(), " Geom_OffsetSurface : VIso");
7fd59977 1215
1216 TColgp_Array1OfPnt Poles( 1, Approx.NbPoles());
1217 TColStd_Array1OfReal Knots( 1, Approx.NbKnots());
1218 TColStd_Array1OfInteger Mults( 1, Approx.NbKnots());
1219
1220 Approx.Poles(1, Poles);
1221 Knots = Approx.Knots()->Array1();
1222 Mults = Approx.Multiplicities()->Array1();
1223
1224 Handle(Geom_BSplineCurve) C =
1225 new Geom_BSplineCurve( Poles, Knots, Mults, Approx.Degree());
1226 return C;
1227 }
1228 else
1229 return equivSurf->VIso(VV);
1230}
1231
7fd59977 1232//=======================================================================
1233//function : IsCNu
1234//purpose :
1235//=======================================================================
1236
9f4cd8eb 1237Standard_Boolean Geom_OffsetSurface::IsCNu (const Standard_Integer N) const
1238{
3d58dc49 1239 Standard_RangeError_Raise_if (N < 0, " ");
1240 return basisSurf->IsCNu (N+1);
7fd59977 1241}
1242
7fd59977 1243//=======================================================================
1244//function : IsCNv
1245//purpose :
1246//=======================================================================
1247
9f4cd8eb 1248Standard_Boolean Geom_OffsetSurface::IsCNv (const Standard_Integer N) const
1249{
7fd59977 1250 Standard_RangeError_Raise_if (N < 0, " ");
1251 return basisSurf->IsCNv (N+1);
1252}
1253
7fd59977 1254//=======================================================================
1255//function : IsUPeriodic
1256//purpose :
1257//=======================================================================
1258
1259Standard_Boolean Geom_OffsetSurface::IsUPeriodic () const
1260{
1261 return basisSurf->IsUPeriodic();
1262}
1263
7fd59977 1264//=======================================================================
1265//function : UPeriod
1266//purpose :
1267//=======================================================================
1268
1269Standard_Real Geom_OffsetSurface::UPeriod() const
1270{
1271 return basisSurf->UPeriod();
1272}
1273
7fd59977 1274//=======================================================================
1275//function : IsVPeriodic
1276//purpose :
1277//=======================================================================
1278
1279Standard_Boolean Geom_OffsetSurface::IsVPeriodic () const
1280{
1281 return basisSurf->IsVPeriodic();
1282}
1283
7fd59977 1284//=======================================================================
1285//function : VPeriod
1286//purpose :
1287//=======================================================================
1288
1289Standard_Real Geom_OffsetSurface::VPeriod() const
1290{
1291 return basisSurf->VPeriod();
1292}
1293
7fd59977 1294//=======================================================================
1295//function : IsUClosed
1296//purpose :
1297//=======================================================================
1298
9f4cd8eb 1299Standard_Boolean Geom_OffsetSurface::IsUClosed () const
1300{
7fd59977 1301 Standard_Boolean UClosed;
c04c30b3 1302 Handle(Geom_Surface) SBasis = BasisSurface();
7fd59977 1303
1304 if (SBasis->IsKind (STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1305 Handle(Geom_RectangularTrimmedSurface) St =
1306 Handle(Geom_RectangularTrimmedSurface)::DownCast(SBasis);
1307
c04c30b3 1308 Handle(Geom_Surface) S = Handle(Geom_Surface)::DownCast(St->BasisSurface());
7fd59977 1309 if (S->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
1310 UClosed = SBasis->IsUClosed();
1311 }
1312 else if (S->IsKind (STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
1313 Handle(Geom_SurfaceOfLinearExtrusion) Extru =
3d58dc49 1314 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S);
7fd59977 1315
c04c30b3 1316 Handle(Geom_Curve) C = Extru->BasisCurve();
7fd59977 1317 if (C->IsKind (STANDARD_TYPE(Geom_Circle)) || C->IsKind (STANDARD_TYPE(Geom_Ellipse))) {
1318 UClosed = SBasis->IsUClosed();
1319 }
1320 else { UClosed = Standard_False; }
1321 }
1322 else if (S->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1323 UClosed = SBasis->IsUClosed();
1324 }
1325 else { UClosed = Standard_False; }
1326 }
1327 else {
1328 if (SBasis->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
1329 UClosed = SBasis->IsUClosed();
1330 }
1331 else if (SBasis->IsKind (STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) {
1332 Handle(Geom_SurfaceOfLinearExtrusion) Extru =
3d58dc49 1333 Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(SBasis);
7fd59977 1334
c04c30b3 1335 Handle(Geom_Curve) C = Extru->BasisCurve();
7fd59977 1336 UClosed = (C->IsKind(STANDARD_TYPE(Geom_Circle)) || C->IsKind(STANDARD_TYPE(Geom_Ellipse)));
1337 }
1338 else if (SBasis->IsKind (STANDARD_TYPE(Geom_SurfaceOfRevolution))) {
1339 UClosed = Standard_True;
1340 }
1341 else { UClosed = Standard_False; }
1342 }
1343 return UClosed;
1344}
1345
7fd59977 1346//=======================================================================
1347//function : IsVClosed
1348//purpose :
1349//=======================================================================
1350
9f4cd8eb 1351Standard_Boolean Geom_OffsetSurface::IsVClosed () const
1352{
7fd59977 1353 Standard_Boolean VClosed;
c04c30b3 1354 Handle(Geom_Surface) SBasis = BasisSurface();
7fd59977 1355
1356 if (SBasis->IsKind (STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
1357 Handle(Geom_RectangularTrimmedSurface) St =
1358 Handle(Geom_RectangularTrimmedSurface)::DownCast(SBasis);
1359
c04c30b3 1360 Handle(Geom_Surface) S = Handle(Geom_Surface)::DownCast(St->BasisSurface());
7fd59977 1361 if (S->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
1362 VClosed = SBasis->IsVClosed();
1363 }
1364 else { VClosed = Standard_False; }
1365 }
1366 else {
1367 if (SBasis->IsKind (STANDARD_TYPE(Geom_ElementarySurface))) {
1368 VClosed = SBasis->IsVClosed();
1369 }
1370 else { VClosed = Standard_False; }
1371 }
1372 return VClosed;
1373}
1374
7fd59977 1375//=======================================================================
1376//function : Transform
1377//purpose :
1378//=======================================================================
1379
9f4cd8eb 1380void Geom_OffsetSurface::Transform (const gp_Trsf& T)
7fd59977 1381{
3d58dc49 1382 basisSurf->Transform (T);
1383 offsetValue *= T.ScaleFactor();
1384 equivSurf.Nullify();
7fd59977 1385}
1386
1387//=======================================================================
1388//function : TransformParameters
1389//purpose :
1390//=======================================================================
1391
9f4cd8eb 1392void Geom_OffsetSurface::TransformParameters(Standard_Real& U, Standard_Real& V,
1393 const gp_Trsf& T) const
7fd59977 1394{
1395 basisSurf->TransformParameters(U,V,T);
1396 if(!equivSurf.IsNull()) equivSurf->TransformParameters(U,V,T);
1397}
1398
1399//=======================================================================
1400//function : ParametricTransformation
1401//purpose :
1402//=======================================================================
1403
9f4cd8eb 1404gp_GTrsf2d Geom_OffsetSurface::ParametricTransformation (const gp_Trsf& T) const
7fd59977 1405{
1406 return basisSurf->ParametricTransformation(T);
1407}
1408
1409//=======================================================================
1410//function : Surface
1411//purpose : Trouve si elle existe, une surface non offset, equivalente
1412// a l'offset surface.
1413//=======================================================================
9f4cd8eb 1414
7fd59977 1415Handle(Geom_Surface) Geom_OffsetSurface::Surface() const
1416{
1417 if (offsetValue == 0.0) return basisSurf; // Cas direct
1418
1419 Standard_Real Tol = Precision::Confusion();
1420 Handle(Geom_Surface) Result, Base;
1421 Result.Nullify();
1422 Handle(Standard_Type) TheType = basisSurf->DynamicType();
1423 Standard_Boolean IsTrimmed;
1d47d8d0 1424 Standard_Real U1 = 0., V1 = 0., U2 = 0., V2 = 0.;
7fd59977 1425
1426 // Preambule pour les surface trimmes
1427 if (TheType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1428 Handle(Geom_RectangularTrimmedSurface) S =
1429 Handle(Geom_RectangularTrimmedSurface)::DownCast(basisSurf);
1430 Base = S->BasisSurface();
1431 TheType = Base->DynamicType();
1432 S->Bounds(U1,U2,V1,V2);
1433 IsTrimmed = Standard_True;
1434 }
3d58dc49 1435 else {
1436 IsTrimmed = Standard_False;
1437 Base = basisSurf;
1438 }
7fd59977 1439
1440 // Traite les surfaces cannonique
3d58dc49 1441 if (TheType == STANDARD_TYPE(Geom_Plane))
7fd59977 1442 {
1443 Handle(Geom_Plane) P =
1444 Handle(Geom_Plane)::DownCast(Base);
1445 gp_Vec T = P->Position().XDirection()^P->Position().YDirection();
1446 T *= offsetValue;
1447 Result = Handle(Geom_Plane)::DownCast(P->Translated(T));
1448 }
1449 else if (TheType == STANDARD_TYPE(Geom_CylindricalSurface))
1450 {
1451 Handle(Geom_CylindricalSurface) C =
1452 Handle(Geom_CylindricalSurface)::DownCast(Base);
1453 Standard_Real Radius = C->Radius();
1454 gp_Ax3 Axis = C->Position();
1455 if (Axis.Direct())
1456 Radius += offsetValue;
1457 else
1458 Radius -= offsetValue;
1459 if ( Radius >= Tol ) {
1460 Result = new Geom_CylindricalSurface( Axis, Radius);
1461 }
1462 else if ( Radius <= -Tol ){
c6541a0c 1463 Axis.Rotate(gp_Ax1(Axis.Location(),Axis.Direction()),M_PI);
7fd59977 1464 Result = new Geom_CylindricalSurface( Axis, Abs(Radius));
1465 Result->UReverse();
1466 }
1467 else
1468 {
3d58dc49 1469 // surface degeneree
7fd59977 1470 }
1471 }
1472 else if (TheType == STANDARD_TYPE(Geom_ConicalSurface))
1473 {
1474 Handle(Geom_ConicalSurface) C =
1475 Handle(Geom_ConicalSurface)::DownCast(Base);
4052fe71 1476 gp_Ax3 anAxis = C->Position();
1477 Standard_Boolean isDirect = anAxis.Direct();
1478 Standard_Real anAlpha = C->SemiAngle();
1479 Standard_Real aRadius;
1480 if (isDirect)
1481 {
1482 aRadius = C->RefRadius() + offsetValue * Cos (anAlpha);
7fd59977 1483 }
4052fe71 1484 else
1485 {
1486 aRadius = C->RefRadius() - offsetValue * Cos (anAlpha);
1487 }
1488 if (aRadius >= 0.)
1489 {
1490 gp_Vec aZ (anAxis.Direction());
1491 if (isDirect)
1492 {
1493 aZ *= -offsetValue * Sin (anAlpha);
1494 }
1495 else
1496 {
1497 aZ *= offsetValue * Sin (anAlpha);
1498 }
1499 anAxis.Translate (aZ);
1500 Result = new Geom_ConicalSurface (anAxis, anAlpha, aRadius);
1501 }
1502 else
7fd59977 1503 {
3d58dc49 1504 // surface degeneree
7fd59977 1505 }
1506 }
1507 else if (TheType == STANDARD_TYPE(Geom_SphericalSurface)) {
1508 Handle(Geom_SphericalSurface) S =
1509 Handle(Geom_SphericalSurface)::DownCast(Base);
1510 Standard_Real Radius = S->Radius();
1511 gp_Ax3 Axis = S->Position();
1512 if (Axis.Direct())
1513 Radius += offsetValue;
1514 else
1515 Radius -= offsetValue;
1516 if ( Radius >= Tol) {
1517 Result = new Geom_SphericalSurface(Axis, Radius);
1518 }
1519 else if ( Radius <= -Tol ) {
c6541a0c 1520 Axis.Rotate(gp_Ax1(Axis.Location(),Axis.Direction()),M_PI);
7fd59977 1521 Axis.ZReverse();
1522 Result = new Geom_SphericalSurface(Axis, -Radius);
1523 Result->UReverse();
1524 }
1525 else {
3d58dc49 1526 // surface degeneree
7fd59977 1527 }
1528 }
1529 else if (TheType == STANDARD_TYPE(Geom_ToroidalSurface))
1530
1531 {
1532 Handle(Geom_ToroidalSurface)
1533 S = Handle(Geom_ToroidalSurface)::DownCast(Base);
1534 Standard_Real MajorRadius = S->MajorRadius();
1535 Standard_Real MinorRadius = S->MinorRadius();
1536 gp_Ax3 Axis = S->Position();
1537 if (MinorRadius <= MajorRadius)
1538 {
1539 if (Axis.Direct())
3d58dc49 1540 MinorRadius += offsetValue;
7fd59977 1541 else
3d58dc49 1542 MinorRadius -= offsetValue;
7fd59977 1543 if (MinorRadius >= Tol)
3d58dc49 1544 Result = new Geom_ToroidalSurface(Axis,MajorRadius,MinorRadius);
1545 // else if (MinorRadius <= -Tol)
1546 // Result->UReverse();
7fd59977 1547 else
1548 {
3d58dc49 1549 // surface degeneree
7fd59977 1550 }
1551 }
1552 }
1553
1554 // S'il le faut on trimme le resultat
1555 if (IsTrimmed && !Result.IsNull()) {
1556 Base = Result;
1557 Result = new Geom_RectangularTrimmedSurface (Base, U1, U2, V1,V2);
1558 }
1559
1560 return Result;
1561}
1562
9f4cd8eb 1563//=======================================================================
1564//function : UOsculatingSurface
1565//purpose :
1566//=======================================================================
1567
1568Standard_Boolean Geom_OffsetSurface::UOsculatingSurface(const Standard_Real U, const Standard_Real V,
1569 Standard_Boolean& t, Handle(Geom_BSplineSurface)& L) const
7fd59977 1570{
1571 return myOscSurf.UOscSurf(U,V,t,L);
1572}
1573
9f4cd8eb 1574//=======================================================================
1575//function : VOsculatingSurface
1576//purpose :
1577//=======================================================================
1578
1579Standard_Boolean Geom_OffsetSurface::VOsculatingSurface(const Standard_Real U, const Standard_Real V,
1580 Standard_Boolean& t, Handle(Geom_BSplineSurface)& L) const
7fd59977 1581{
1582 return myOscSurf.VOscSurf(U,V,t,L);
1583}
1584
7fd59977 1585//=======================================================================
1586//function :
1587//purpose : private
1588//=======================================================================
9f4cd8eb 1589
7fd59977 1590void Geom_OffsetSurface::SetD0(const Standard_Real U, const Standard_Real V,
9f4cd8eb 1591 gp_Pnt& P,
c1a487e4 1592 const gp_Vec& D1U, const gp_Vec& D1V) const // First Derivative
7fd59977 1593{
9f4cd8eb 1594 const Standard_Real MagTol=0.000000001;
7fd59977 1595
c1a487e4 1596 gp_Vec aNorm = D1U.Crossed(D1V);
1597 if (aNorm.SquareMagnitude() > MagTol * MagTol)
3d58dc49 1598 {
c1a487e4 1599 // Non singular case. Simple computations.
1600 aNorm.Normalize();
1601 P.SetXYZ(P.XYZ() + offsetValue * aNorm.XYZ());
3d58dc49 1602 }
c1a487e4 1603 else
3d58dc49 1604 {
c1a487e4 1605 Standard_Boolean AlongU = Standard_False,
1606 AlongV = Standard_False;
1607 Handle(Geom_BSplineSurface) L;
1608 Standard_Boolean IsOpposite=Standard_False;
1609 AlongU = UOsculatingSurface(U,V,IsOpposite,L);
1610 AlongV = VOsculatingSurface(U,V,IsOpposite,L);
1611 gp_Dir Normal;
1612 CSLib_NormalStatus NStatus;
1613 Standard_Integer MaxOrder=3;
3d58dc49 1614 TColgp_Array2OfVec DerNUV(0,MaxOrder,0,MaxOrder);
1615 TColgp_Array2OfVec DerSurf(0,MaxOrder+1,0,MaxOrder+1);
1616 Standard_Integer OrderU,OrderV;
1617 Standard_Real Umin,Umax,Vmin,Vmax;
1618 Bounds(Umin,Umax,Vmin,Vmax);
1619 DerSurf.SetValue(1, 0, D1U);
1620 DerSurf.SetValue(0, 1, D1V);
1621 derivatives(MaxOrder,1,U,V,basisSurf,0,0,AlongU,AlongV,L,DerNUV,DerSurf);
1622
c1a487e4 1623 Standard_Real signe = 1.0;
1624 if ((AlongV || AlongU) && IsOpposite)
1625 signe = -1;
1626
3d58dc49 1627 CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
1628 if (NStatus == CSLib_Defined)
1629 P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
a07a0416 1630 else
1631 {
1632 if (NStatus == CSLib_InfinityOfSolutions &&
1633 D1U.SquareMagnitude() + D1V.SquareMagnitude() > MagTol * MagTol)
1634 {
1635 // Use non-null derivative as normal direction in degenerated case.
1636 gp_Vec aNorm = D1U.SquareMagnitude() > MagTol * MagTol ? D1U : D1V;
1637 aNorm.Normalize();
1638
1639 P.SetXYZ(P.XYZ() + offsetValue * signe * aNorm.XYZ());
1640 return;
1641 }
3d58dc49 1642 Geom_UndefinedValue::Raise();
a07a0416 1643 }
3d58dc49 1644 }
7fd59977 1645}
1646
1647//=======================================================================
1648//function :
1649//purpose : private
1650//=======================================================================/
9f4cd8eb 1651
1652void Geom_OffsetSurface::SetD1(const Standard_Real U, const Standard_Real V,
1653 gp_Pnt& P,
1654 gp_Vec& D1U, gp_Vec& D1V, // First derivative
1655 const gp_Vec& D2UU, const gp_Vec& D2VV, const gp_Vec& D2UV) const // Second derivative
7fd59977 1656{
9f4cd8eb 1657 const Standard_Real MagTol=0.000000001;
a07a0416 1658
1659 // Check offset side.
1660 Handle(Geom_BSplineSurface) L;
c1a487e4 1661 Standard_Boolean AlongU = Standard_False,
1662 AlongV = Standard_False;
a07a0416 1663 Standard_Boolean IsOpposite=Standard_False;
c1a487e4 1664 AlongU = UOsculatingSurface(U,V,IsOpposite,L);
1665 AlongV = VOsculatingSurface(U,V,IsOpposite,L);
1666 Standard_Real signe = 1.0;
1667 if ((AlongV || AlongU) && IsOpposite)
1668 signe = -1.0;
1669
1670 Standard_Integer MaxOrder = 0;
1671 gp_Vec aNorm = D1U.Crossed(D1V);
1672 if (aNorm.SquareMagnitude() > MagTol * MagTol)
a07a0416 1673 {
7fd59977 1674 MaxOrder=0;
a07a0416 1675
1676 if (!AlongV && !AlongU)
1677 {
c1a487e4 1678 // AlongU or AlongV leads to more complex D1 computations,
1679 // try to compute D0 and D1 much simpler.
1680 aNorm.Normalize();
1681 P.SetXYZ(P.XYZ() + offsetValue * signe * aNorm.XYZ());
a07a0416 1682
c1a487e4 1683 gp_Vec aN0(aNorm.XYZ()), aN1U, aN1V;
a07a0416 1684 Standard_Real aScale = (D1U^D1V).Dot(aN0);
1685 aN1U.SetX(D2UU.Y() * D1V.Z() + D1U.Y() * D2UV.Z()
1686 - D2UU.Z() * D1V.Y() - D1U.Z() * D2UV.Y());
1687 aN1U.SetY((D2UU.X() * D1V.Z() + D1U.X() * D2UV.Z()
1688 - D2UU.Z() * D1V.X() - D1U.Z() * D2UV.X() ) * -1.0);
1689 aN1U.SetZ(D2UU.X() * D1V.Y() + D1U.X() * D2UV.Y()
1690 - D2UU.Y() * D1V.X() - D1U.Y() * D2UV.X());
1691 Standard_Real aScaleU = aN1U.Dot(aN0);
1692 aN1U.Subtract(aScaleU * aN0);
1693 aN1U /= aScale;
1694
1695 aN1V.SetX(D2UV.Y() * D1V.Z() + D2VV.Z() * D1U.Y()
1696 - D2UV.Z() * D1V.Y() - D2VV.Y() * D1U.Z());
1697 aN1V.SetY((D2UV.X() * D1V.Z() + D2VV.Z() * D1U.X()
1698 - D2UV.Z() * D1V.X() - D2VV.X() * D1U.Z()) * -1.0);
1699 aN1V.SetZ(D2UV.X() * D1V.Y() + D2VV.Y() * D1U.X()
1700 - D2UV.Y() * D1V.X() - D2VV.X() * D1U.Y());
1701 Standard_Real aScaleV = aN1V.Dot(aN0);
1702 aN1V.Subtract(aScaleV * aN0);
1703 aN1V /= aScale;
1704
1705 D1U += offsetValue * signe * aN1U;
1706 D1V += offsetValue * signe * aN1V;
1707
1708 return;
1709 }
1710 }
7fd59977 1711 else
1712 MaxOrder=3;
a07a0416 1713
7fd59977 1714 Standard_Integer OrderU,OrderV;
1715 TColgp_Array2OfVec DerNUV(0,MaxOrder+1,0,MaxOrder+1);
1716 TColgp_Array2OfVec DerSurf(0,MaxOrder+2,0,MaxOrder+2);
1717 Standard_Real Umin,Umax,Vmin,Vmax;
1718 Bounds(Umin,Umax,Vmin,Vmax);
1719 DerSurf.SetValue(1, 0, D1U);
1720 DerSurf.SetValue(0, 1, D1V);
a07a0416 1721 DerSurf.SetValue(1, 1, D2UV);
1722 DerSurf.SetValue(2, 0, D2UU);
1723 DerSurf.SetValue(0, 2, D2VV);
7fd59977 1724 derivatives(MaxOrder,2,U,V,basisSurf,1,1,AlongU,AlongV,L,DerNUV,DerSurf);
3d58dc49 1725
c1a487e4 1726 gp_Dir Normal;
1727 CSLib_NormalStatus NStatus;
7fd59977 1728 CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
1729 if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
3d58dc49 1730
7fd59977 1731 P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
3d58dc49 1732
7fd59977 1733 D1U = DerSurf(1,0)
1734 + offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
1735 D1V = DerSurf(0,1)
1736 + offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
7fd59977 1737}
1738
1739//=======================================================================
1740//function :
1741//purpose : private
1742//=======================================================================/
9f4cd8eb 1743
7fd59977 1744void Geom_OffsetSurface::SetD2(const Standard_Real U, const Standard_Real V,
9f4cd8eb 1745 gp_Pnt& P,
1746 gp_Vec& D1U, gp_Vec& D1V,
1747 gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
1748 const gp_Vec& d3u, const gp_Vec& d3v,
1749 const gp_Vec& d3uuv, const gp_Vec& d3uvv) const
7fd59977 1750{
9f4cd8eb 1751 const Standard_Real MagTol=0.000000001;
1752
1753 gp_Dir Normal;
7fd59977 1754 CSLib_NormalStatus NStatus;
1755 CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
9f4cd8eb 1756
1757 const Standard_Integer MaxOrder = (NStatus == CSLib_Defined)? 0 : 3;
7fd59977 1758 Standard_Integer OrderU,OrderV;
1759 TColgp_Array2OfVec DerNUV(0,MaxOrder+2,0,MaxOrder+2);
1760 TColgp_Array2OfVec DerSurf(0,MaxOrder+3,0,MaxOrder+3);
1761 Standard_Real Umin,Umax,Vmin,Vmax;
1762 Bounds(Umin,Umax,Vmin,Vmax);
1763 DerSurf.SetValue(1, 0, D1U);
1764 DerSurf.SetValue(0, 1, D1V);
1765 DerSurf.SetValue(1, 1, D2UV);
1766 DerSurf.SetValue(2, 0, D2U);
1767 DerSurf.SetValue(0, 2, D2V);
1768 DerSurf.SetValue(3, 0, d3u);
1769 DerSurf.SetValue(2, 1, d3uuv);
1770 DerSurf.SetValue(1, 2, d3uvv);
1771 DerSurf.SetValue(0, 3, d3v);
1772 //*********************
3d58dc49 1773
7fd59977 1774 Handle(Geom_BSplineSurface) L;
7fd59977 1775 Standard_Boolean IsOpposite=Standard_False;
9f4cd8eb 1776 const Standard_Boolean AlongU = UOsculatingSurface(U,V,IsOpposite,L);
1777 const Standard_Boolean AlongV = VOsculatingSurface(U,V,IsOpposite,L);
1778 const Standard_Real signe = ((AlongV || AlongU) && IsOpposite)? -1. : 1.;
7fd59977 1779 derivatives(MaxOrder,3,U,V,basisSurf,2,2,AlongU,AlongV,L,DerNUV,DerSurf);
3d58dc49 1780
7fd59977 1781 CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
1782 if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
3d58dc49 1783
7fd59977 1784 P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
3d58dc49 1785
7fd59977 1786 D1U = DerSurf(1,0)
1787 + offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
1788 D1V = DerSurf(0,1)
1789 + offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
3d58dc49 1790
7fd59977 1791 D2U = basisSurf->DN(U,V,2,0)
1792 + signe * offsetValue * CSLib::DNNormal(2,0,DerNUV,OrderU,OrderV);
1793 D2V = basisSurf->DN(U,V,0,2)
1794 + signe * offsetValue * CSLib::DNNormal(0,2,DerNUV,OrderU,OrderV);
1795 D2UV = basisSurf->DN(U,V,1,1)
1796 + signe * offsetValue * CSLib::DNNormal(1,1,DerNUV,OrderU,OrderV);
1797}
1798
7fd59977 1799//=======================================================================
1800//function :
1801//purpose : private
1802//=======================================================================/
9f4cd8eb 1803
7fd59977 1804void Geom_OffsetSurface::SetD3(const Standard_Real U, const Standard_Real V,
9f4cd8eb 1805 gp_Pnt& P,
1806 gp_Vec& D1U, gp_Vec& D1V,
1807 gp_Vec& D2U, gp_Vec& D2V, gp_Vec& D2UV,
1808 gp_Vec& D3U, gp_Vec& D3V, gp_Vec& D3UUV, gp_Vec& D3UVV) const
7fd59977 1809{
9f4cd8eb 1810 const Standard_Real MagTol=0.000000001;
1811
1812 gp_Dir Normal;
7fd59977 1813 CSLib_NormalStatus NStatus;
1814 CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
9f4cd8eb 1815 const Standard_Integer MaxOrder = (NStatus == CSLib_Defined)? 0 : 3;
7fd59977 1816 Standard_Integer OrderU,OrderV;
1817 TColgp_Array2OfVec DerNUV(0,MaxOrder+3,0,MaxOrder+3);
1818 TColgp_Array2OfVec DerSurf(0,MaxOrder+4,0,MaxOrder+4);
1819 Standard_Real Umin,Umax,Vmin,Vmax;
1820 Bounds(Umin,Umax,Vmin,Vmax);
3d58dc49 1821
7fd59977 1822 DerSurf.SetValue(1, 0, D1U);
1823 DerSurf.SetValue(0, 1, D1V);
1824 DerSurf.SetValue(1, 1, D2UV);
1825 DerSurf.SetValue(2, 0, D2U);
1826 DerSurf.SetValue(0, 2, D2V);
1827 DerSurf.SetValue(3, 0, D3U);
1828 DerSurf.SetValue(2, 1, D3UUV);
1829 DerSurf.SetValue(1, 2, D3UVV);
1830 DerSurf.SetValue(0, 3, D3V);
3d58dc49 1831
1832
7fd59977 1833 //*********************
1834 Handle(Geom_BSplineSurface) L;
7fd59977 1835 Standard_Boolean IsOpposite=Standard_False;
9f4cd8eb 1836 const Standard_Boolean AlongU = UOsculatingSurface(U,V,IsOpposite,L);
1837 const Standard_Boolean AlongV = VOsculatingSurface(U,V,IsOpposite,L);
1838 const Standard_Real signe = ((AlongV || AlongU) && IsOpposite)? -1. : 1.;
7fd59977 1839 derivatives(MaxOrder,3,U,V,basisSurf,3,3,AlongU,AlongV,L,DerNUV,DerSurf);
3d58dc49 1840
7fd59977 1841 CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
1842 if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
3d58dc49 1843
7fd59977 1844 P.SetXYZ(P.XYZ() + offsetValue * signe * Normal.XYZ());
3d58dc49 1845
7fd59977 1846 D1U = DerSurf(1,0)
1847 + offsetValue * signe * CSLib::DNNormal(1,0,DerNUV,OrderU,OrderV);
1848 D1V = DerSurf(0,1)
1849 + offsetValue * signe * CSLib::DNNormal(0,1,DerNUV,OrderU,OrderV);
3d58dc49 1850
7fd59977 1851 D2U = basisSurf->DN(U,V,2,0)
1852 + signe * offsetValue * CSLib::DNNormal(2,0,DerNUV,OrderU,OrderV);
1853 D2V = basisSurf->DN(U,V,0,2)
1854 + signe * offsetValue * CSLib::DNNormal(0,2,DerNUV,OrderU,OrderV);
1855 D2UV = basisSurf->DN(U,V,1,1)
1856 + signe * offsetValue * CSLib::DNNormal(1,1,DerNUV,OrderU,OrderV);
1857 D3U = basisSurf->DN(U,V,3,0)
1858 + signe * offsetValue * CSLib::DNNormal(3,0,DerNUV,OrderU,OrderV);
1859 D3V = basisSurf->DN(U,V,0,3)
1860 + signe * offsetValue * CSLib::DNNormal(0,3,DerNUV,OrderU,OrderV);
1861 D3UUV = basisSurf->DN(U,V,2,1)
1862 + signe * offsetValue * CSLib::DNNormal(2,1,DerNUV,OrderU,OrderV);
1863 D3UVV = basisSurf->DN(U,V,1,2)
1864 + signe * offsetValue * CSLib::DNNormal(1,2,DerNUV,OrderU,OrderV);
1865}
1866
7fd59977 1867//=======================================================================
1868//function : SetDN
1869//purpose :
1870//=======================================================================
1871
9f4cd8eb 1872gp_Vec Geom_OffsetSurface::SetDN ( const Standard_Real U, const Standard_Real V,
3d58dc49 1873 const Standard_Integer Nu, const Standard_Integer Nv,
9f4cd8eb 1874 const gp_Vec& D1U, const gp_Vec& D1V) const
7fd59977 1875{
9f4cd8eb 1876 const Standard_Real MagTol=0.000000001;
1877
1878 gp_Dir Normal;
7fd59977 1879 CSLib_NormalStatus NStatus;
1880 CSLib::Normal (D1U, D1V, MagTol, NStatus, Normal);
9f4cd8eb 1881 const Standard_Integer MaxOrder = (NStatus == CSLib_Defined)? 0 : 3;
7fd59977 1882 Standard_Integer OrderU,OrderV;
1883 TColgp_Array2OfVec DerNUV(0,MaxOrder+Nu,0,MaxOrder+Nu);
1884 TColgp_Array2OfVec DerSurf(0,MaxOrder+Nu+1,0,MaxOrder+Nv+1);
1885 Standard_Real Umin,Umax,Vmin,Vmax;
1886 Bounds(Umin,Umax,Vmin,Vmax);
3d58dc49 1887
7fd59977 1888 DerSurf.SetValue(1, 0, D1U);
1889 DerSurf.SetValue(0, 1, D1V);
9f4cd8eb 1890
7fd59977 1891 //*********************
1892 Handle(Geom_BSplineSurface) L;
7fd59977 1893 // Is there any osculatingsurface along U or V;
1894 Standard_Boolean IsOpposite=Standard_False;
9f4cd8eb 1895 const Standard_Boolean AlongU = UOsculatingSurface(U,V,IsOpposite,L);
1896 const Standard_Boolean AlongV = VOsculatingSurface(U,V,IsOpposite,L);
1897 const Standard_Real signe = ((AlongV || AlongU) && IsOpposite)? -1. : 1.;
7fd59977 1898 derivatives(MaxOrder,1,U,V,basisSurf,Nu,Nv,AlongU,AlongV,L,DerNUV,DerSurf);
3d58dc49 1899
7fd59977 1900 CSLib::Normal(MaxOrder,DerNUV,MagTol,U,V,Umin,Umax,Vmin,Vmax,NStatus,Normal,OrderU,OrderV);
1901 if (NStatus != CSLib_Defined) Geom_UndefinedValue::Raise();
3d58dc49 1902
9f4cd8eb 1903 gp_Vec D = basisSurf->DN(U,V,Nu,Nv)
7fd59977 1904 + signe * offsetValue * CSLib::DNNormal(Nu,Nv,DerNUV,OrderU,OrderV);
3d58dc49 1905
7fd59977 1906 return D;
1907}