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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 #include <Approx_CurvilinearParameter.hxx>
18 
19 #include <Adaptor2d_Curve2d.hxx>
20 #include <Adaptor3d_Curve.hxx>
21 #include <Adaptor3d_CurveOnSurface.hxx>
22 #include <Adaptor3d_Surface.hxx>
23 #include <AdvApprox_ApproxAFunction.hxx>
24 #include <AdvApprox_PrefAndRec.hxx>
25 #include <Approx_CurvlinFunc.hxx>
26 #include <CPnts_AbscissaPoint.hxx>
27 #include <GCPnts_AbscissaPoint.hxx>
28 #include <Geom2d_BSplineCurve.hxx>
29 #include <Geom_BSplineCurve.hxx>
30 #include <GeomAbs_Shape.hxx>
31 #include <GeomAdaptor_Curve.hxx>
32 #include <GeomAdaptor_Surface.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Pnt2d.hxx>
35 #include <gp_Vec.hxx>
36 #include <gp_Vec2d.hxx>
37 #include <math_Vector.hxx>
38 #include <Precision.hxx>
39 #include <Standard_ConstructionError.hxx>
40 #include <Standard_OutOfRange.hxx>
41 #include <TColgp_Array1OfPnt.hxx>
42 #include <TColgp_Array1OfPnt2d.hxx>
43 #include <TColStd_Array1OfReal.hxx>
44 #include <TColStd_HArray1OfInteger.hxx>
45 #include <TColStd_HArray1OfReal.hxx>
46 
47 #ifdef OCCT_DEBUG_CHRONO
48 #include <OSD_Timer.hxx>
49 static OSD_Chronometer chr_total, chr_init, chr_approx;
50 
51 Standard_Real t_total, t_init, t_approx;
InitChron(OSD_Chronometer & ch)52 void InitChron(OSD_Chronometer& ch)
53 {
54     ch.Reset();
55     ch.Start();
56 }
57 
ResultChron(OSD_Chronometer & ch,Standard_Real & time)58 void ResultChron( OSD_Chronometer & ch, Standard_Real & time)
59 {
60     Standard_Real tch ;
61     ch.Stop();
62     ch.Show(tch);
63     time=time +tch;
64 }
65 
66 Standard_IMPORT Standard_Integer uparam_count;
67 Standard_IMPORT Standard_Real t_uparam;
68 #endif
69 
70 //=======================================================================
71 //class : Approx_CurvilinearParameter_EvalCurv
72 //purpose  : case of a free 3D curve
73 //=======================================================================
74 
75 class Approx_CurvilinearParameter_EvalCurv : public AdvApprox_EvaluatorFunction
76 {
77  public:
Approx_CurvilinearParameter_EvalCurv(const Handle (Approx_CurvlinFunc)& theFunc,Standard_Real First,Standard_Real Last)78   Approx_CurvilinearParameter_EvalCurv (const Handle(Approx_CurvlinFunc)& theFunc,
79                                         Standard_Real First, Standard_Real Last)
80     : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
81 
82   virtual void Evaluate (Standard_Integer *Dimension,
83 		         Standard_Real     StartEnd[2],
84                          Standard_Real    *Parameter,
85                          Standard_Integer *DerivativeRequest,
86                          Standard_Real    *Result, // [Dimension]
87                          Standard_Integer *ErrorCode);
88 
89  private:
90   Handle(Approx_CurvlinFunc) fonct;
91   Standard_Real StartEndSav[2];
92 };
93 
Evaluate(Standard_Integer * Dimension,Standard_Real * StartEnd,Standard_Real * Param,Standard_Integer * Order,Standard_Real * Result,Standard_Integer * ErrorCode)94 void Approx_CurvilinearParameter_EvalCurv::Evaluate (Standard_Integer * Dimension,
95                                                      Standard_Real    * StartEnd,
96                                                      Standard_Real    * Param,
97                                                      Standard_Integer * Order,
98                                                      Standard_Real    * Result,
99                                                      Standard_Integer * ErrorCode)
100 {
101   *ErrorCode = 0;
102   Standard_Real S = *Param;
103   TColStd_Array1OfReal Res(0, 2);
104   Standard_Integer i;
105 
106 // Dimension is incorrect
107   if (*Dimension != 3) {
108     *ErrorCode = 1;
109   }
110 // Parameter is incorrect
111   if ( S < StartEnd[0] || S > StartEnd[1] ) {
112     *ErrorCode = 2;
113   }
114 
115   if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
116     {
117       fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
118       StartEndSav[0]=StartEnd[0];
119       StartEndSav[1]=StartEnd[1];
120     }
121 
122   if(!fonct->EvalCase1(S, *Order, Res)) {
123     *ErrorCode = 3;
124   }
125 
126   for(i = 0; i <= 2; i++)
127     Result[i] = Res(i);
128 }
129 
Approx_CurvilinearParameter(const Handle (Adaptor3d_Curve)& C3D,const Standard_Real Tol,const GeomAbs_Shape Order,const Standard_Integer MaxDegree,const Standard_Integer MaxSegments)130 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor3d_Curve)& C3D,
131 							 const Standard_Real Tol,
132 							 const GeomAbs_Shape Order,
133 							 const Standard_Integer MaxDegree,
134 							 const Standard_Integer MaxSegments)
135 : myMaxError2d1(0.0),
136   myMaxError2d2(0.0)
137 {
138 #ifdef OCCT_DEBUG_CHRONO
139   t_total = t_init = t_approx = t_uparam = 0;
140   uparam_count = 0;
141   InitChron(chr_total);
142 #endif
143   myCase = 1;
144 // Initialisation of input parameters of AdvApprox
145 
146   Standard_Integer Num1DSS=0, Num2DSS=0, Num3DSS=1;
147   Handle(TColStd_HArray1OfReal) OneDTolNul, TwoDTolNul;
148   Handle(TColStd_HArray1OfReal) ThreeDTol  = new TColStd_HArray1OfReal(1,Num3DSS);
149   ThreeDTol->Init(Tol);
150 
151 #ifdef OCCT_DEBUG_CHRONO
152   InitChron(chr_init);
153 #endif
154   Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C3D, Tol/10);
155 #ifdef OCCT_DEBUG_CHRONO
156   ResultChron(chr_init, t_init);
157 #endif
158 
159   Standard_Real FirstS = fonct->FirstParameter();
160   Standard_Real  LastS = fonct->LastParameter();
161 
162   Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
163   TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
164   fonct->Intervals(CutPnts_C2,GeomAbs_C2);
165   Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
166   TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
167   fonct->Intervals(CutPnts_C3,GeomAbs_C3);
168   AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
169 
170 #ifdef OCCT_DEBUG_CHRONO
171   InitChron(chr_approx);
172 #endif
173 
174   Approx_CurvilinearParameter_EvalCurv evC (fonct, FirstS, LastS);
175   AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
176 				     OneDTolNul, TwoDTolNul, ThreeDTol,
177 				     FirstS, LastS, Order,
178 				     MaxDegree, MaxSegments,
179 				     evC, CutTool);
180 
181 #ifdef OCCT_DEBUG_CHRONO
182   ResultChron(chr_approx, t_approx);
183 #endif
184 
185   myDone      = aApprox.IsDone();
186   myHasResult = aApprox.HasResult();
187 
188   if (myHasResult) {
189     TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
190     aApprox.Poles(1,Poles);
191     Handle(TColStd_HArray1OfReal)    Knots = aApprox.Knots();
192     Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
193     Standard_Integer Degree = aApprox.Degree();
194     myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
195   }
196   myMaxError3d = aApprox.MaxError(3,1);
197 
198 #ifdef OCCT_DEBUG_CHRONO
199   ResultChron(chr_total, t_total);
200 
201   std::cout<<" total reparametrization time = "<<t_total<<std::endl;
202   std::cout<<"initialization time = "<<t_init<<std::endl;
203   std::cout<<"approximation time = "<<t_approx<<std::endl;
204   std::cout<<"total time for uparam computation = "<<t_uparam<<std::endl;
205   std::cout<<"number uparam calles = "<<uparam_count<<std::endl;
206 #endif
207 }
208 
209 //=======================================================================
210 //class : Approx_CurvilinearParameter_EvalCurvOnSurf
211 //purpose  : case of a curve on one surface
212 //=======================================================================
213 
214 class Approx_CurvilinearParameter_EvalCurvOnSurf : public AdvApprox_EvaluatorFunction
215 {
216  public:
Approx_CurvilinearParameter_EvalCurvOnSurf(const Handle (Approx_CurvlinFunc)& theFunc,Standard_Real First,Standard_Real Last)217   Approx_CurvilinearParameter_EvalCurvOnSurf (const Handle(Approx_CurvlinFunc)& theFunc,
218                                               Standard_Real First, Standard_Real Last)
219     : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
220 
221   virtual void Evaluate (Standard_Integer *Dimension,
222 		         Standard_Real     StartEnd[2],
223                          Standard_Real    *Parameter,
224                          Standard_Integer *DerivativeRequest,
225                          Standard_Real    *Result, // [Dimension]
226                          Standard_Integer *ErrorCode);
227 
228  private:
229   Handle(Approx_CurvlinFunc) fonct;
230   Standard_Real StartEndSav[2];
231 };
232 
Evaluate(Standard_Integer * Dimension,Standard_Real * StartEnd,Standard_Real * Param,Standard_Integer * Order,Standard_Real * Result,Standard_Integer * ErrorCode)233 void Approx_CurvilinearParameter_EvalCurvOnSurf::Evaluate (Standard_Integer * Dimension,
234                                                            Standard_Real    * StartEnd,
235                                                            Standard_Real    * Param,
236                                                            Standard_Integer * Order,
237                                                            Standard_Real    * Result,
238                                                            Standard_Integer * ErrorCode)
239 {
240   *ErrorCode = 0;
241   Standard_Real S = *Param;
242   TColStd_Array1OfReal Res(0, 4);
243   Standard_Integer i;
244 
245 // Dimension is incorrect
246   if (*Dimension != 5) {
247     *ErrorCode = 1;
248   }
249 // Parameter is incorrect
250   if ( S < StartEnd[0] || S > StartEnd[1] ) {
251     *ErrorCode = 2;
252   }
253 
254   if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
255     {
256       fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
257       StartEndSav[0]=StartEnd[0];
258       StartEndSav[1]=StartEnd[1];
259     }
260 
261   if(!fonct->EvalCase2(S, *Order, Res)) {
262     *ErrorCode = 3;
263   }
264 
265   for(i = 0; i <= 4; i++)
266     Result[i] = Res(i);
267 }
268 
Approx_CurvilinearParameter(const Handle (Adaptor2d_Curve2d)& C2D,const Handle (Adaptor3d_Surface)& Surf,const Standard_Real Tol,const GeomAbs_Shape Order,const Standard_Integer MaxDegree,const Standard_Integer MaxSegments)269 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor2d_Curve2d)& C2D,
270 							 const Handle(Adaptor3d_Surface)& Surf,
271 							 const Standard_Real Tol,
272 							 const GeomAbs_Shape Order,
273 							 const Standard_Integer MaxDegree,
274 							 const Standard_Integer MaxSegments)
275 {
276 #ifdef OCCT_DEBUG_CHRONO
277   t_total = t_init = t_approx = t_uparam = 0;
278   uparam_count = 0;
279   InitChron(chr_total);
280 #endif
281   myCase = 2;
282 
283   // Initialisation of input parameters of AdvApprox
284 
285   Standard_Integer Num1DSS=2, Num2DSS=0, Num3DSS=1, i;
286 
287   Handle(TColStd_HArray1OfReal) OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
288   Standard_Real TolV,TolW;
289 
290   ToleranceComputation(C2D,Surf,10,Tol,TolV,TolW);
291   OneDTol->SetValue(1,TolV);
292   OneDTol->SetValue(2,TolW);
293 
294   OneDTol->SetValue(1,Tol);
295   OneDTol->SetValue(2,Tol);
296 
297   Handle(TColStd_HArray1OfReal) TwoDTolNul;
298   Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
299   ThreeDTol->Init(Tol/2.);
300 
301 #ifdef OCCT_DEBUG_CHRONO
302   InitChron(chr_init);
303 #endif
304   Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C2D, Surf, Tol/20);
305 #ifdef OCCT_DEBUG_CHRONO
306   ResultChron(chr_init, t_init);
307 #endif
308 
309   Standard_Real FirstS = fonct->FirstParameter();
310   Standard_Real  LastS = fonct->LastParameter();
311 
312   Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
313   TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
314   fonct->Intervals(CutPnts_C2,GeomAbs_C2);
315   Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
316   TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
317   fonct->Intervals(CutPnts_C3,GeomAbs_C3);
318   AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
319 
320 #ifdef OCCT_DEBUG_CHRONO
321   InitChron(chr_approx);
322 #endif
323 
324   Approx_CurvilinearParameter_EvalCurvOnSurf evCOnS (fonct, FirstS, LastS);
325   AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
326 				     OneDTol, TwoDTolNul, ThreeDTol,
327 				     FirstS, LastS, Order,
328 				     MaxDegree, MaxSegments,
329 				     evCOnS, CutTool);
330 
331 #ifdef OCCT_DEBUG_CHRONO
332   ResultChron(chr_approx, t_approx);
333 #endif
334 
335   myDone      = aApprox.IsDone();
336   myHasResult = aApprox.HasResult();
337 
338   if (myHasResult) {
339     Standard_Integer NbPoles = aApprox.NbPoles();
340     TColgp_Array1OfPnt   Poles  (1,NbPoles);
341     TColgp_Array1OfPnt2d Poles2d(1,NbPoles);
342     TColStd_Array1OfReal Poles1d(1,NbPoles);
343     aApprox.Poles(1,Poles);
344     aApprox.Poles1d(1,Poles1d);
345     for (i=1; i<=NbPoles; i++)
346       Poles2d(i).SetX(Poles1d(i));
347     aApprox.Poles1d(2,Poles1d);
348     for (i=1; i<=NbPoles; i++)
349       Poles2d(i).SetY(Poles1d(i));
350     Handle(TColStd_HArray1OfReal)    Knots = aApprox.Knots();
351     Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
352     Standard_Integer Degree = aApprox.Degree();
353     myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
354     myCurve2d1 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
355   }
356   myMaxError2d1 = Max (aApprox.MaxError(1,1),aApprox.MaxError(1,2));
357   myMaxError3d  = aApprox.MaxError(3,1);
358 
359 #ifdef OCCT_DEBUG_CHRONO
360   ResultChron(chr_total, t_total);
361 
362   std::cout<<" total reparametrization time = "<<t_total<<std::endl;
363   std::cout<<"initialization time = "<<t_init<<std::endl;
364   std::cout<<"approximation time = "<<t_approx<<std::endl;
365   std::cout<<"total time for uparam computation = "<<t_uparam<<std::endl;
366   std::cout<<"number uparam calles = "<<uparam_count<<std::endl;
367 #endif
368 }
369 
370 //=======================================================================
371 //function : Approx_CurvilinearParameter_EvalCurvOn2Surf
372 //purpose  : case of a curve on two surfaces
373 //=======================================================================
374 
375 class Approx_CurvilinearParameter_EvalCurvOn2Surf : public AdvApprox_EvaluatorFunction
376 {
377  public:
Approx_CurvilinearParameter_EvalCurvOn2Surf(const Handle (Approx_CurvlinFunc)& theFunc,Standard_Real First,Standard_Real Last)378   Approx_CurvilinearParameter_EvalCurvOn2Surf (const Handle(Approx_CurvlinFunc)& theFunc,
379                                                Standard_Real First, Standard_Real Last)
380     : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
381 
382   virtual void Evaluate (Standard_Integer *Dimension,
383 		         Standard_Real     StartEnd[2],
384                          Standard_Real    *Parameter,
385                          Standard_Integer *DerivativeRequest,
386                          Standard_Real    *Result, // [Dimension]
387                          Standard_Integer *ErrorCode);
388 
389  private:
390   Handle(Approx_CurvlinFunc) fonct;
391   Standard_Real StartEndSav[2];
392 };
393 
Evaluate(Standard_Integer * Dimension,Standard_Real * StartEnd,Standard_Real * Param,Standard_Integer * Order,Standard_Real * Result,Standard_Integer * ErrorCode)394 void Approx_CurvilinearParameter_EvalCurvOn2Surf::Evaluate (Standard_Integer * Dimension,
395                                                             Standard_Real    * StartEnd,
396                                                             Standard_Real    * Param,
397                                                             Standard_Integer * Order,
398                                                             Standard_Real    * Result,
399                                                             Standard_Integer * ErrorCode)
400 {
401   *ErrorCode = 0;
402   Standard_Real S = *Param;
403   TColStd_Array1OfReal Res(0, 6);
404   Standard_Integer i;
405 
406 // Dimension is incorrect
407   if (*Dimension != 7) {
408     *ErrorCode = 1;
409   }
410 // Parameter is incorrect
411   if ( S < StartEnd[0] || S > StartEnd[1] ) {
412     *ErrorCode = 2;
413   }
414 
415 /*  if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
416     {
417       fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
418       StartEndSav[0]=StartEnd[0];
419       StartEndSav[1]=StartEnd[1];
420     }
421 */
422   if(!fonct->EvalCase3(S, *Order, Res)) {
423     *ErrorCode = 3;
424   }
425 
426   for(i = 0; i <= 6; i++)
427     Result[i] = Res(i);
428 }
429 
Approx_CurvilinearParameter(const Handle (Adaptor2d_Curve2d)& C2D1,const Handle (Adaptor3d_Surface)& Surf1,const Handle (Adaptor2d_Curve2d)& C2D2,const Handle (Adaptor3d_Surface)& Surf2,const Standard_Real Tol,const GeomAbs_Shape Order,const Standard_Integer MaxDegree,const Standard_Integer MaxSegments)430 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor2d_Curve2d)& C2D1,
431 							 const Handle(Adaptor3d_Surface)& Surf1,
432 							 const Handle(Adaptor2d_Curve2d)& C2D2,
433 							 const Handle(Adaptor3d_Surface)& Surf2,
434 							 const Standard_Real Tol,
435 							 const GeomAbs_Shape Order,
436 							 const Standard_Integer MaxDegree,
437 							 const Standard_Integer MaxSegments)
438 {
439   Standard_Integer i;
440 
441 #ifdef OCCT_DEBUG_CHRONO
442   t_total = t_init = t_approx = t_uparam = 0;
443   uparam_count = 0;
444   InitChron(chr_total);
445 #endif
446   myCase = 3;
447 
448   // Initialisation of input parameters of AdvApprox
449 
450   Standard_Integer Num1DSS=4, Num2DSS=0, Num3DSS=1;
451   Handle(TColStd_HArray1OfReal) OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
452 
453   Standard_Real TolV,TolW;
454   ToleranceComputation(C2D1,Surf1,10,Tol,TolV,TolW);
455   OneDTol->SetValue(1,TolV);
456   OneDTol->SetValue(2,TolW);
457 
458   ToleranceComputation(C2D2,Surf2,10,Tol,TolV,TolW);
459   OneDTol->SetValue(3,TolV);
460   OneDTol->SetValue(4,TolW);
461 
462   Handle(TColStd_HArray1OfReal) TwoDTolNul;
463   Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
464   ThreeDTol->Init(Tol/2);
465 
466 #ifdef OCCT_DEBUG_CHRONO
467   InitChron(chr_init);
468 #endif
469   Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C2D1, C2D2, Surf1, Surf2, Tol/20);
470 #ifdef OCCT_DEBUG_CHRONO
471   ResultChron(chr_init, t_init);
472 #endif
473 
474   Standard_Real FirstS = fonct->FirstParameter();
475   Standard_Real  LastS = fonct->LastParameter();
476 
477   Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
478   TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
479   fonct->Intervals(CutPnts_C2,GeomAbs_C2);
480   Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
481   TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
482   fonct->Intervals(CutPnts_C3,GeomAbs_C3);
483   AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
484 
485 #ifdef OCCT_DEBUG_CHRONO
486   InitChron(chr_approx);
487 #endif
488 
489   Approx_CurvilinearParameter_EvalCurvOn2Surf evCOn2S (fonct, FirstS, LastS);
490   AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
491 				     OneDTol, TwoDTolNul, ThreeDTol,
492 				     FirstS, LastS, Order,
493 				     MaxDegree, MaxSegments,
494 				     evCOn2S, CutTool);
495 
496 #ifdef OCCT_DEBUG_CHRONO
497   ResultChron(chr_approx, t_approx);
498 #endif
499 
500   myDone      = aApprox.IsDone();
501   myHasResult = aApprox.HasResult();
502 
503   if (myHasResult) {
504     Standard_Integer NbPoles = aApprox.NbPoles();
505     TColgp_Array1OfPnt   Poles  (1,NbPoles);
506     TColgp_Array1OfPnt2d Poles2d(1,NbPoles);
507     TColStd_Array1OfReal Poles1d(1,NbPoles);
508     aApprox.Poles(1,Poles);
509     aApprox.Poles1d(1,Poles1d);
510     for (i=1; i<=NbPoles; i++)
511       Poles2d(i).SetX(Poles1d(i));
512     aApprox.Poles1d(2,Poles1d);
513     for (i=1; i<=NbPoles; i++)
514       Poles2d(i).SetY(Poles1d(i));
515     Handle(TColStd_HArray1OfReal)    Knots = aApprox.Knots();
516     Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
517     Standard_Integer Degree = aApprox.Degree();
518     myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
519     myCurve2d1 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
520     aApprox.Poles1d(3,Poles1d);
521     for (i=1; i<=NbPoles; i++)
522       Poles2d(i).SetX(Poles1d(i));
523     aApprox.Poles1d(4,Poles1d);
524     for (i=1; i<=NbPoles; i++)
525       Poles2d(i).SetY(Poles1d(i));
526     myCurve2d2 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
527   }
528   myMaxError2d1 = Max (aApprox.MaxError(1,1),aApprox.MaxError(1,2));
529   myMaxError2d2 = Max (aApprox.MaxError(1,3),aApprox.MaxError(1,4));
530   myMaxError3d  = aApprox.MaxError(3,1);
531 
532 #ifdef OCCT_DEBUG_CHRONO
533   ResultChron(chr_total, t_total);
534 
535   std::cout<<" total reparametrization time = "<<t_total<<std::endl;
536   std::cout<<"initialization time = "<<t_init<<std::endl;
537   std::cout<<"approximation time = "<<t_approx<<std::endl;
538   std::cout<<"total time for uparam computation = "<<t_uparam<<std::endl;
539   std::cout<<"number uparam calles = "<<uparam_count<<std::endl;
540 #endif
541 }
542 
543 //=======================================================================
544 //function : IsDone
545 //purpose  :
546 //=======================================================================
547 
IsDone() const548  Standard_Boolean Approx_CurvilinearParameter::IsDone() const
549 {
550   return myDone;
551 }
552 
553 //=======================================================================
554 //function : HasResult
555 //purpose  :
556 //=======================================================================
557 
HasResult() const558  Standard_Boolean Approx_CurvilinearParameter::HasResult() const
559 {
560   return myHasResult;
561 }
562 
563 //=======================================================================
564 //function : Curve3d
565 //purpose  : returns the Bspline curve corresponding to the reparametrized 3D curve
566 //=======================================================================
567 
Handle(Geom_BSplineCurve)568  Handle(Geom_BSplineCurve) Approx_CurvilinearParameter::Curve3d() const
569 {
570   return myCurve3d;
571 }
572 
573 //=======================================================================
574 //function : MaxError3d
575 //purpose  : returns the maximum error on the reparametrized 3D curve
576 //=======================================================================
577 
MaxError3d() const578  Standard_Real Approx_CurvilinearParameter::MaxError3d() const
579 {
580   return myMaxError3d;
581 }
582 
583 //=======================================================================
584 //function : Curve2d1
585 //purpose  : returns the BsplineCurve representing the reparametrized 2D curve on the
586 //           first surface (case of a curve on one or two surfaces)
587 //=======================================================================
588 
Handle(Geom2d_BSplineCurve)589  Handle(Geom2d_BSplineCurve) Approx_CurvilinearParameter::Curve2d1() const
590 {
591   return myCurve2d1;
592 }
593 
594 //=======================================================================
595 //function : MaxError2d1
596 //purpose  : returns the maximum error on the first reparametrized 2D curve
597 //=======================================================================
598 
MaxError2d1() const599  Standard_Real Approx_CurvilinearParameter::MaxError2d1() const
600 {
601   return myMaxError2d1;
602 }
603 
604 //=======================================================================
605 //function : Curve2d2
606 //purpose  : returns the BsplineCurve representing the reparametrized 2D curve on the
607 //           second surface (case of a curve on two surfaces)
608 //=======================================================================
609 
Handle(Geom2d_BSplineCurve)610  Handle(Geom2d_BSplineCurve) Approx_CurvilinearParameter::Curve2d2() const
611 {
612   return myCurve2d2;
613 }
614 
615 //=======================================================================
616 //function : MaxError2d2
617 //purpose  : returns the maximum error on the second reparametrized 2D curve
618 //=======================================================================
619 
MaxError2d2() const620  Standard_Real Approx_CurvilinearParameter::MaxError2d2() const
621 {
622   return myMaxError2d2;
623 }
624 
625 //=======================================================================
626 //function : Dump
627 //purpose  : print the maximum errors(s)
628 //=======================================================================
629 
Dump(Standard_OStream & o) const630 void Approx_CurvilinearParameter::Dump(Standard_OStream& o) const
631 {
632   o << "Dump of Approx_CurvilinearParameter" << std::endl;
633   if (myCase==2 || myCase==3)
634     o << "myMaxError2d1 = " << myMaxError2d1 << std::endl;
635   if (myCase==3)
636     o << "myMaxError2d2 = " << myMaxError2d2 << std::endl;
637   o << "myMaxError3d = " << myMaxError3d << std::endl;
638 }
639 
640 //=======================================================================
641 //function : ToleranceComputation
642 //purpose  :
643 //=======================================================================
644 
ToleranceComputation(const Handle (Adaptor2d_Curve2d)& C2D,const Handle (Adaptor3d_Surface)& S,const Standard_Integer MaxNumber,const Standard_Real Tol,Standard_Real & TolV,Standard_Real & TolW)645 void Approx_CurvilinearParameter::ToleranceComputation(const Handle(Adaptor2d_Curve2d) &C2D,
646 						       const Handle(Adaptor3d_Surface) &S,
647 						       const Standard_Integer MaxNumber,
648 						       const Standard_Real Tol,
649 						       Standard_Real &TolV, Standard_Real &TolW)
650 {
651   Standard_Real FirstU = C2D->FirstParameter(),
652                 LastU  = C2D->LastParameter();
653 //  Standard_Real parU, Max_dS_dv=1.,Max_dS_dw=1.;
654   Standard_Real Max_dS_dv=1.,Max_dS_dw=1.;
655   gp_Pnt P;
656   gp_Pnt2d pntVW;
657   gp_Vec dS_dv,dS_dw;
658 
659   for (Standard_Integer i=1; i<=MaxNumber; i++) {
660     pntVW = C2D->Value(FirstU + (i-1)*(LastU-FirstU)/(MaxNumber-1));
661     S->D1(pntVW.X(),pntVW.Y(),P,dS_dv,dS_dw);
662     Max_dS_dv = Max (Max_dS_dv, dS_dv.Magnitude());
663     Max_dS_dw = Max (Max_dS_dw, dS_dw.Magnitude());
664   }
665   TolV = Tol / (4.*Max_dS_dv);
666   TolW = Tol / (4.*Max_dS_dw);
667 
668 #ifdef OCCT_DEBUG
669   std::cout << "TolV = " << TolV << std::endl;
670   std::cout << "TolW = " << TolW << std::endl;
671 #endif
672 }
673