1 // Created on: 1997-08-22
2 // Created by: Sergey SOKOLOV
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <Approx_CurvilinearParameter.ixx>
19 #include <Adaptor3d_Curve.hxx>
20 #include <GCPnts_AbscissaPoint.hxx>
22 #include <gp_Pnt2d.hxx>
24 #include <gp_Vec2d.hxx>
25 #include <GeomAbs_Shape.hxx>
26 #include <AdvApprox_ApproxAFunction.hxx>
27 #include <Geom_BSplineCurve.hxx>
28 #include <TColStd_HArray1OfReal.hxx>
29 #include <TColStd_HArray1OfInteger.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <GeomAdaptor_HCurve.hxx>
32 #include <GeomAdaptor_HSurface.hxx>
33 #include <TColStd_Array1OfReal.hxx>
34 #include <AdvApprox_PrefAndRec.hxx>
35 #include <Adaptor3d_CurveOnSurface.hxx>
36 #include <Precision.hxx>
37 #include <Geom2d_BSplineCurve.hxx>
38 #include <TColgp_Array1OfPnt2d.hxx>
39 #include <math_Vector.hxx>
40 #include <CPnts_AbscissaPoint.hxx>
41 #include <Approx_CurvlinFunc.hxx>
43 #ifdef __OCC_DEBUG_CHRONO
44 #include <OSD_Timer.hxx>
45 static OSD_Chronometer chr_total, chr_init, chr_approx;
47 Standard_Real t_total, t_init, t_approx;
48 void InitChron(OSD_Chronometer& ch)
54 void ResultChron( OSD_Chronometer & ch, Standard_Real & time)
62 Standard_IMPORT Standard_Integer uparam_count;
63 Standard_IMPORT Standard_Real t_uparam;
66 //=======================================================================
67 //class : Approx_CurvilinearParameter_EvalCurv
68 //purpose : case of a free 3D curve
69 //=======================================================================
71 class Approx_CurvilinearParameter_EvalCurv : public AdvApprox_EvaluatorFunction
74 Approx_CurvilinearParameter_EvalCurv (const Handle(Approx_CurvlinFunc)& theFunc,
75 Standard_Real First, Standard_Real Last)
76 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
78 virtual void Evaluate (Standard_Integer *Dimension,
79 Standard_Real StartEnd[2],
80 Standard_Real *Parameter,
81 Standard_Integer *DerivativeRequest,
82 Standard_Real *Result, // [Dimension]
83 Standard_Integer *ErrorCode);
86 Handle(Approx_CurvlinFunc) fonct;
87 Standard_Real StartEndSav[2];
90 void Approx_CurvilinearParameter_EvalCurv::Evaluate (Standard_Integer * Dimension,
91 Standard_Real * StartEnd,
92 Standard_Real * Param,
93 Standard_Integer * Order,
94 Standard_Real * Result,
95 Standard_Integer * ErrorCode)
98 Standard_Real S = *Param;
99 TColStd_Array1OfReal Res(0, 2);
102 // Dimension is incorrect
103 if (*Dimension != 3) {
106 // Parameter is incorrect
107 if ( S < StartEnd[0] || S > StartEnd[1] ) {
111 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
113 fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
114 StartEndSav[0]=StartEnd[0];
115 StartEndSav[1]=StartEnd[1];
118 if(!fonct->EvalCase1(S, *Order, Res)) {
122 for(i = 0; i <= 2; i++)
126 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor3d_HCurve)& C3D,
127 const Standard_Real Tol,
128 const GeomAbs_Shape Order,
129 const Standard_Integer MaxDegree,
130 const Standard_Integer MaxSegments)
132 #ifdef __OCC_DEBUG_CHRONO
133 t_total = t_init = t_approx = t_uparam = 0;
135 InitChron(chr_total);
138 // Initialisation of input parameters of AdvApprox
140 Standard_Integer Num1DSS=0, Num2DSS=0, Num3DSS=1;
141 Handle(TColStd_HArray1OfReal) OneDTolNul, TwoDTolNul;
142 Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
143 ThreeDTol->Init(Tol);
145 #ifdef __OCC_DEBUG_CHRONO
148 Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C3D, Tol/10);
149 #ifdef __OCC_DEBUG_CHRONO
150 ResultChron(chr_init, t_init);
153 Standard_Real FirstS = fonct->FirstParameter();
154 Standard_Real LastS = fonct->LastParameter();
156 Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
157 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
158 fonct->Intervals(CutPnts_C2,GeomAbs_C2);
159 Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
160 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
161 fonct->Intervals(CutPnts_C3,GeomAbs_C3);
162 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
164 #ifdef __OCC_DEBUG_CHRONO
165 InitChron(chr_approx);
168 Approx_CurvilinearParameter_EvalCurv evC (fonct, FirstS, LastS);
169 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
170 OneDTolNul, TwoDTolNul, ThreeDTol,
171 FirstS, LastS, Order,
172 MaxDegree, MaxSegments,
175 #ifdef __OCC_DEBUG_CHRONO
176 ResultChron(chr_approx, t_approx);
179 myDone = aApprox.IsDone();
180 myHasResult = aApprox.HasResult();
183 TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
184 aApprox.Poles(1,Poles);
185 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
186 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
187 Standard_Integer Degree = aApprox.Degree();
188 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
190 myMaxError3d = aApprox.MaxError(3,1);
192 #ifdef __OCC_DEBUG_CHRONO
193 ResultChron(chr_total, t_total);
195 cout<<" total reparametrization time = "<<t_total<<endl;
196 cout<<"initialization time = "<<t_init<<endl;
197 cout<<"approximation time = "<<t_approx<<endl;
198 cout<<"total time for uparam computation = "<<t_uparam<<endl;
199 cout<<"number uparam calles = "<<uparam_count<<endl;
203 //=======================================================================
204 //class : Approx_CurvilinearParameter_EvalCurvOnSurf
205 //purpose : case of a curve on one surface
206 //=======================================================================
208 class Approx_CurvilinearParameter_EvalCurvOnSurf : public AdvApprox_EvaluatorFunction
211 Approx_CurvilinearParameter_EvalCurvOnSurf (const Handle(Approx_CurvlinFunc)& theFunc,
212 Standard_Real First, Standard_Real Last)
213 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
215 virtual void Evaluate (Standard_Integer *Dimension,
216 Standard_Real StartEnd[2],
217 Standard_Real *Parameter,
218 Standard_Integer *DerivativeRequest,
219 Standard_Real *Result, // [Dimension]
220 Standard_Integer *ErrorCode);
223 Handle(Approx_CurvlinFunc) fonct;
224 Standard_Real StartEndSav[2];
227 void Approx_CurvilinearParameter_EvalCurvOnSurf::Evaluate (Standard_Integer * Dimension,
228 Standard_Real * StartEnd,
229 Standard_Real * Param,
230 Standard_Integer * Order,
231 Standard_Real * Result,
232 Standard_Integer * ErrorCode)
235 Standard_Real S = *Param;
236 TColStd_Array1OfReal Res(0, 4);
239 // Dimension is incorrect
240 if (*Dimension != 5) {
243 // Parameter is incorrect
244 if ( S < StartEnd[0] || S > StartEnd[1] ) {
248 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
250 fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
251 StartEndSav[0]=StartEnd[0];
252 StartEndSav[1]=StartEnd[1];
255 if(!fonct->EvalCase2(S, *Order, Res)) {
259 for(i = 0; i <= 4; i++)
263 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor2d_HCurve2d)& C2D,
264 const Handle(Adaptor3d_HSurface)& Surf,
265 const Standard_Real Tol,
266 const GeomAbs_Shape Order,
267 const Standard_Integer MaxDegree,
268 const Standard_Integer MaxSegments)
270 #ifdef __OCC_DEBUG_CHRONO
271 t_total = t_init = t_approx = t_uparam = 0;
273 InitChron(chr_total);
277 // Initialisation of input parameters of AdvApprox
279 Standard_Integer Num1DSS=2, Num2DSS=0, Num3DSS=1, i;
281 Handle(TColStd_HArray1OfReal) OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
282 Standard_Real TolV,TolW;
284 ToleranceComputation(C2D,Surf,10,Tol,TolV,TolW);
285 OneDTol->SetValue(1,TolV);
286 OneDTol->SetValue(2,TolW);
288 OneDTol->SetValue(1,Tol);
289 OneDTol->SetValue(2,Tol);
291 Handle(TColStd_HArray1OfReal) TwoDTolNul;
292 Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
293 ThreeDTol->Init(Tol/2.);
295 #ifdef __OCC_DEBUG_CHRONO
298 Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C2D, Surf, Tol/20);
299 #ifdef __OCC_DEBUG_CHRONO
300 ResultChron(chr_init, t_init);
303 Standard_Real FirstS = fonct->FirstParameter();
304 Standard_Real LastS = fonct->LastParameter();
306 Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
307 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
308 fonct->Intervals(CutPnts_C2,GeomAbs_C2);
309 Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
310 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
311 fonct->Intervals(CutPnts_C3,GeomAbs_C3);
312 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
314 #ifdef __OCC_DEBUG_CHRONO
315 InitChron(chr_approx);
318 Approx_CurvilinearParameter_EvalCurvOnSurf evCOnS (fonct, FirstS, LastS);
319 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
320 OneDTol, TwoDTolNul, ThreeDTol,
321 FirstS, LastS, Order,
322 MaxDegree, MaxSegments,
325 #ifdef __OCC_DEBUG_CHRONO
326 ResultChron(chr_approx, t_approx);
329 myDone = aApprox.IsDone();
330 myHasResult = aApprox.HasResult();
333 Standard_Integer NbPoles = aApprox.NbPoles();
334 TColgp_Array1OfPnt Poles (1,NbPoles);
335 TColgp_Array1OfPnt2d Poles2d(1,NbPoles);
336 TColStd_Array1OfReal Poles1d(1,NbPoles);
337 aApprox.Poles(1,Poles);
338 aApprox.Poles1d(1,Poles1d);
339 for (i=1; i<=NbPoles; i++)
340 Poles2d(i).SetX(Poles1d(i));
341 aApprox.Poles1d(2,Poles1d);
342 for (i=1; i<=NbPoles; i++)
343 Poles2d(i).SetY(Poles1d(i));
344 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
345 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
346 Standard_Integer Degree = aApprox.Degree();
347 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
348 myCurve2d1 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
350 myMaxError2d1 = Max (aApprox.MaxError(1,1),aApprox.MaxError(1,2));
351 myMaxError3d = aApprox.MaxError(3,1);
353 #ifdef __OCC_DEBUG_CHRONO
354 ResultChron(chr_total, t_total);
356 cout<<" total reparametrization time = "<<t_total<<endl;
357 cout<<"initialization time = "<<t_init<<endl;
358 cout<<"approximation time = "<<t_approx<<endl;
359 cout<<"total time for uparam computation = "<<t_uparam<<endl;
360 cout<<"number uparam calles = "<<uparam_count<<endl;
364 //=======================================================================
365 //function : Approx_CurvilinearParameter_EvalCurvOn2Surf
366 //purpose : case of a curve on two surfaces
367 //=======================================================================
369 class Approx_CurvilinearParameter_EvalCurvOn2Surf : public AdvApprox_EvaluatorFunction
372 Approx_CurvilinearParameter_EvalCurvOn2Surf (const Handle(Approx_CurvlinFunc)& theFunc,
373 Standard_Real First, Standard_Real Last)
374 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
376 virtual void Evaluate (Standard_Integer *Dimension,
377 Standard_Real StartEnd[2],
378 Standard_Real *Parameter,
379 Standard_Integer *DerivativeRequest,
380 Standard_Real *Result, // [Dimension]
381 Standard_Integer *ErrorCode);
384 Handle(Approx_CurvlinFunc) fonct;
385 Standard_Real StartEndSav[2];
388 void Approx_CurvilinearParameter_EvalCurvOn2Surf::Evaluate (Standard_Integer * Dimension,
389 Standard_Real * StartEnd,
390 Standard_Real * Param,
391 Standard_Integer * Order,
392 Standard_Real * Result,
393 Standard_Integer * ErrorCode)
396 Standard_Real S = *Param;
397 TColStd_Array1OfReal Res(0, 6);
400 // Dimension is incorrect
401 if (*Dimension != 7) {
404 // Parameter is incorrect
405 if ( S < StartEnd[0] || S > StartEnd[1] ) {
409 /* if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
411 fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
412 StartEndSav[0]=StartEnd[0];
413 StartEndSav[1]=StartEnd[1];
416 if(!fonct->EvalCase3(S, *Order, Res)) {
420 for(i = 0; i <= 6; i++)
424 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor2d_HCurve2d)& C2D1,
425 const Handle(Adaptor3d_HSurface)& Surf1,
426 const Handle(Adaptor2d_HCurve2d)& C2D2,
427 const Handle(Adaptor3d_HSurface)& Surf2,
428 const Standard_Real Tol,
429 const GeomAbs_Shape Order,
430 const Standard_Integer MaxDegree,
431 const Standard_Integer MaxSegments)
435 #ifdef __OCC_DEBUG_CHRONO
436 t_total = t_init = t_approx = t_uparam = 0;
438 InitChron(chr_total);
442 // Initialisation of input parameters of AdvApprox
444 Standard_Integer Num1DSS=4, Num2DSS=0, Num3DSS=1;
445 Handle(TColStd_HArray1OfReal) OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
447 Standard_Real TolV,TolW;
448 ToleranceComputation(C2D1,Surf1,10,Tol,TolV,TolW);
449 OneDTol->SetValue(1,TolV);
450 OneDTol->SetValue(2,TolW);
452 ToleranceComputation(C2D2,Surf2,10,Tol,TolV,TolW);
453 OneDTol->SetValue(3,TolV);
454 OneDTol->SetValue(4,TolW);
456 Handle(TColStd_HArray1OfReal) TwoDTolNul;
457 Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
458 ThreeDTol->Init(Tol/2);
460 #ifdef __OCC_DEBUG_CHRONO
463 Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C2D1, C2D2, Surf1, Surf2, Tol/20);
464 #ifdef __OCC_DEBUG_CHRONO
465 ResultChron(chr_init, t_init);
468 Standard_Real FirstS = fonct->FirstParameter();
469 Standard_Real LastS = fonct->LastParameter();
471 Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
472 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
473 fonct->Intervals(CutPnts_C2,GeomAbs_C2);
474 Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
475 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
476 fonct->Intervals(CutPnts_C3,GeomAbs_C3);
477 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
479 #ifdef __OCC_DEBUG_CHRONO
480 InitChron(chr_approx);
483 Approx_CurvilinearParameter_EvalCurvOn2Surf evCOn2S (fonct, FirstS, LastS);
484 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
485 OneDTol, TwoDTolNul, ThreeDTol,
486 FirstS, LastS, Order,
487 MaxDegree, MaxSegments,
490 #ifdef __OCC_DEBUG_CHRONO
491 ResultChron(chr_approx, t_approx);
494 myDone = aApprox.IsDone();
495 myHasResult = aApprox.HasResult();
498 Standard_Integer NbPoles = aApprox.NbPoles();
499 TColgp_Array1OfPnt Poles (1,NbPoles);
500 TColgp_Array1OfPnt2d Poles2d(1,NbPoles);
501 TColStd_Array1OfReal Poles1d(1,NbPoles);
502 aApprox.Poles(1,Poles);
503 aApprox.Poles1d(1,Poles1d);
504 for (i=1; i<=NbPoles; i++)
505 Poles2d(i).SetX(Poles1d(i));
506 aApprox.Poles1d(2,Poles1d);
507 for (i=1; i<=NbPoles; i++)
508 Poles2d(i).SetY(Poles1d(i));
509 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
510 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
511 Standard_Integer Degree = aApprox.Degree();
512 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
513 myCurve2d1 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
514 aApprox.Poles1d(3,Poles1d);
515 for (i=1; i<=NbPoles; i++)
516 Poles2d(i).SetX(Poles1d(i));
517 aApprox.Poles1d(4,Poles1d);
518 for (i=1; i<=NbPoles; i++)
519 Poles2d(i).SetY(Poles1d(i));
520 myCurve2d2 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
522 myMaxError2d1 = Max (aApprox.MaxError(1,1),aApprox.MaxError(1,2));
523 myMaxError2d2 = Max (aApprox.MaxError(1,3),aApprox.MaxError(1,4));
524 myMaxError3d = aApprox.MaxError(3,1);
526 #ifdef __OCC_DEBUG_CHRONO
527 ResultChron(chr_total, t_total);
529 cout<<" total reparametrization time = "<<t_total<<endl;
530 cout<<"initialization time = "<<t_init<<endl;
531 cout<<"approximation time = "<<t_approx<<endl;
532 cout<<"total time for uparam computation = "<<t_uparam<<endl;
533 cout<<"number uparam calles = "<<uparam_count<<endl;
537 //=======================================================================
540 //=======================================================================
542 Standard_Boolean Approx_CurvilinearParameter::IsDone() const
547 //=======================================================================
548 //function : HasResult
550 //=======================================================================
552 Standard_Boolean Approx_CurvilinearParameter::HasResult() const
557 //=======================================================================
559 //purpose : returns the Bspline curve corresponding to the reparametrized 3D curve
560 //=======================================================================
562 Handle(Geom_BSplineCurve) Approx_CurvilinearParameter::Curve3d() const
567 //=======================================================================
568 //function : MaxError3d
569 //purpose : returns the maximum error on the reparametrized 3D curve
570 //=======================================================================
572 Standard_Real Approx_CurvilinearParameter::MaxError3d() const
577 //=======================================================================
578 //function : Curve2d1
579 //purpose : returns the BsplineCurve representing the reparametrized 2D curve on the
580 // first surface (case of a curve on one or two surfaces)
581 //=======================================================================
583 Handle(Geom2d_BSplineCurve) Approx_CurvilinearParameter::Curve2d1() const
588 //=======================================================================
589 //function : MaxError2d1
590 //purpose : returns the maximum error on the first reparametrized 2D curve
591 //=======================================================================
593 Standard_Real Approx_CurvilinearParameter::MaxError2d1() const
595 return myMaxError2d1;
598 //=======================================================================
599 //function : Curve2d2
600 //purpose : returns the BsplineCurve representing the reparametrized 2D curve on the
601 // second surface (case of a curve on two surfaces)
602 //=======================================================================
604 Handle(Geom2d_BSplineCurve) Approx_CurvilinearParameter::Curve2d2() const
609 //=======================================================================
610 //function : MaxError2d2
611 //purpose : returns the maximum error on the second reparametrized 2D curve
612 //=======================================================================
614 Standard_Real Approx_CurvilinearParameter::MaxError2d2() const
616 return myMaxError2d2;
619 //=======================================================================
621 //purpose : print the maximum errors(s)
622 //=======================================================================
624 void Approx_CurvilinearParameter::Dump(Standard_OStream& o) const
626 o << "Dump of Approx_CurvilinearParameter" << endl;
627 if (myCase==2 || myCase==3)
628 o << "myMaxError2d1 = " << myMaxError2d1 << endl;
630 o << "myMaxError2d2 = " << myMaxError2d2 << endl;
631 o << "myMaxError3d = " << myMaxError3d << endl;
634 //=======================================================================
635 //function : ToleranceComputation
637 //=======================================================================
639 void Approx_CurvilinearParameter::ToleranceComputation(const Handle(Adaptor2d_HCurve2d) &C2D,
640 const Handle(Adaptor3d_HSurface) &S,
641 const Standard_Integer MaxNumber,
642 const Standard_Real Tol,
643 Standard_Real &TolV, Standard_Real &TolW)
645 Standard_Real FirstU = C2D->FirstParameter(),
646 LastU = C2D->LastParameter();
647 // Standard_Real parU, Max_dS_dv=1.,Max_dS_dw=1.;
648 Standard_Real Max_dS_dv=1.,Max_dS_dw=1.;
653 for (Standard_Integer i=1; i<=MaxNumber; i++) {
654 pntVW = C2D->Value(FirstU + (i-1)*(LastU-FirstU)/(MaxNumber-1));
655 S->D1(pntVW.X(),pntVW.Y(),P,dS_dv,dS_dw);
656 Max_dS_dv = Max (Max_dS_dv, dS_dv.Magnitude());
657 Max_dS_dw = Max (Max_dS_dw, dS_dw.Magnitude());
659 TolV = Tol / (4.*Max_dS_dv);
660 TolW = Tol / (4.*Max_dS_dw);
663 cout << "TolV = " << TolV << endl;
664 cout << "TolW = " << TolW << endl;