1 // File: Approx_CurvilinearParameter.cxx
2 // Created: Fri Aug 22 09:11:03 1997
3 // Author: Sergey SOKOLOV
4 // <ssv@nonox.nnov.matra-dtv.fr>
6 #include <Approx_CurvilinearParameter.ixx>
8 #include <Adaptor3d_Curve.hxx>
9 #include <GCPnts_AbscissaPoint.hxx>
11 #include <gp_Pnt2d.hxx>
13 #include <gp_Vec2d.hxx>
14 #include <GeomAbs_Shape.hxx>
15 #include <AdvApprox_ApproxAFunction.hxx>
16 #include <Geom_BSplineCurve.hxx>
17 #include <TColStd_HArray1OfReal.hxx>
18 #include <TColStd_HArray1OfInteger.hxx>
19 #include <TColgp_Array1OfPnt.hxx>
20 #include <GeomAdaptor_HCurve.hxx>
21 #include <GeomAdaptor_HSurface.hxx>
22 #include <TColStd_Array1OfReal.hxx>
23 #include <AdvApprox_PrefAndRec.hxx>
24 #include <Adaptor3d_CurveOnSurface.hxx>
25 #include <Precision.hxx>
26 #include <Geom2d_BSplineCurve.hxx>
27 #include <TColgp_Array1OfPnt2d.hxx>
28 #include <math_Vector.hxx>
29 #include <CPnts_AbscissaPoint.hxx>
30 #include <Approx_CurvlinFunc.hxx>
33 #include <OSD_Timer.hxx>
34 static OSD_Chronometer chr_total, chr_init, chr_approx;
36 Standard_Real t_total, t_init, t_approx;
37 void InitChron(OSD_Chronometer& ch)
43 void ResultChron( OSD_Chronometer & ch, Standard_Real & time)
51 Standard_IMPORT Standard_Integer uparam_count;
52 Standard_IMPORT Standard_Real t_uparam;
55 //=======================================================================
56 //class : Approx_CurvilinearParameter_EvalCurv
57 //purpose : case of a free 3D curve
58 //=======================================================================
60 class Approx_CurvilinearParameter_EvalCurv : public AdvApprox_EvaluatorFunction
63 Approx_CurvilinearParameter_EvalCurv (const Handle(Approx_CurvlinFunc)& theFunc,
64 Standard_Real First, Standard_Real Last)
65 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
67 virtual void Evaluate (Standard_Integer *Dimension,
68 Standard_Real StartEnd[2],
69 Standard_Real *Parameter,
70 Standard_Integer *DerivativeRequest,
71 Standard_Real *Result, // [Dimension]
72 Standard_Integer *ErrorCode);
75 Handle(Approx_CurvlinFunc) fonct;
76 Standard_Real StartEndSav[2];
79 void Approx_CurvilinearParameter_EvalCurv::Evaluate (Standard_Integer * Dimension,
80 Standard_Real * StartEnd,
81 Standard_Real * Param,
82 Standard_Integer * Order,
83 Standard_Real * Result,
84 Standard_Integer * ErrorCode)
87 Standard_Real S = *Param;
88 TColStd_Array1OfReal Res(0, 2);
91 // Dimension is incorrect
92 if (*Dimension != 3) {
95 // Parameter is incorrect
96 if ( S < StartEnd[0] || S > StartEnd[1] ) {
100 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
102 fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
103 StartEndSav[0]=StartEnd[0];
104 StartEndSav[1]=StartEnd[1];
107 if(!fonct->EvalCase1(S, *Order, Res)) {
111 for(i = 0; i <= 2; i++)
115 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor3d_HCurve)& C3D,
116 const Standard_Real Tol,
117 const GeomAbs_Shape Order,
118 const Standard_Integer MaxDegree,
119 const Standard_Integer MaxSegments)
122 t_total = t_init = t_approx = t_uparam = 0;
124 InitChron(chr_total);
127 // Initialisation of input parameters of AdvApprox
129 Standard_Integer Num1DSS=0, Num2DSS=0, Num3DSS=1;
130 Handle(TColStd_HArray1OfReal) OneDTolNul, TwoDTolNul;
131 Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
132 ThreeDTol->Init(Tol);
137 Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C3D, Tol/10);
139 ResultChron(chr_init, t_init);
142 Standard_Real FirstS = fonct->FirstParameter();
143 Standard_Real LastS = fonct->LastParameter();
145 Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
146 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
147 fonct->Intervals(CutPnts_C2,GeomAbs_C2);
148 Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
149 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
150 fonct->Intervals(CutPnts_C3,GeomAbs_C3);
151 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
154 InitChron(chr_approx);
157 Approx_CurvilinearParameter_EvalCurv evC (fonct, FirstS, LastS);
158 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
159 OneDTolNul, TwoDTolNul, ThreeDTol,
160 FirstS, LastS, Order,
161 MaxDegree, MaxSegments,
165 ResultChron(chr_approx, t_approx);
168 myDone = aApprox.IsDone();
169 myHasResult = aApprox.HasResult();
172 TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
173 aApprox.Poles(1,Poles);
174 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
175 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
176 Standard_Integer Degree = aApprox.Degree();
177 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
179 myMaxError3d = aApprox.MaxError(3,1);
182 ResultChron(chr_total, t_total);
184 cout<<" total reparametrization time = "<<t_total<<endl;
185 cout<<"initialization time = "<<t_init<<endl;
186 cout<<"approximation time = "<<t_approx<<endl;
187 cout<<"total time for uparam computation = "<<t_uparam<<endl;
188 cout<<"number uparam calles = "<<uparam_count<<endl;
192 //=======================================================================
193 //class : Approx_CurvilinearParameter_EvalCurvOnSurf
194 //purpose : case of a curve on one surface
195 //=======================================================================
197 class Approx_CurvilinearParameter_EvalCurvOnSurf : public AdvApprox_EvaluatorFunction
200 Approx_CurvilinearParameter_EvalCurvOnSurf (const Handle(Approx_CurvlinFunc)& theFunc,
201 Standard_Real First, Standard_Real Last)
202 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
204 virtual void Evaluate (Standard_Integer *Dimension,
205 Standard_Real StartEnd[2],
206 Standard_Real *Parameter,
207 Standard_Integer *DerivativeRequest,
208 Standard_Real *Result, // [Dimension]
209 Standard_Integer *ErrorCode);
212 Handle(Approx_CurvlinFunc) fonct;
213 Standard_Real StartEndSav[2];
216 void Approx_CurvilinearParameter_EvalCurvOnSurf::Evaluate (Standard_Integer * Dimension,
217 Standard_Real * StartEnd,
218 Standard_Real * Param,
219 Standard_Integer * Order,
220 Standard_Real * Result,
221 Standard_Integer * ErrorCode)
224 Standard_Real S = *Param;
225 TColStd_Array1OfReal Res(0, 4);
228 // Dimension is incorrect
229 if (*Dimension != 5) {
232 // Parameter is incorrect
233 if ( S < StartEnd[0] || S > StartEnd[1] ) {
237 if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
239 fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
240 StartEndSav[0]=StartEnd[0];
241 StartEndSav[1]=StartEnd[1];
244 if(!fonct->EvalCase2(S, *Order, Res)) {
248 for(i = 0; i <= 4; i++)
252 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor2d_HCurve2d)& C2D,
253 const Handle(Adaptor3d_HSurface)& Surf,
254 const Standard_Real Tol,
255 const GeomAbs_Shape Order,
256 const Standard_Integer MaxDegree,
257 const Standard_Integer MaxSegments)
260 t_total = t_init = t_approx = t_uparam = 0;
262 InitChron(chr_total);
266 // Initialisation of input parameters of AdvApprox
268 Standard_Integer Num1DSS=2, Num2DSS=0, Num3DSS=1, i;
270 Handle(TColStd_HArray1OfReal) OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
271 Standard_Real TolV,TolW;
273 ToleranceComputation(C2D,Surf,10,Tol,TolV,TolW);
274 OneDTol->SetValue(1,TolV);
275 OneDTol->SetValue(2,TolW);
277 OneDTol->SetValue(1,Tol);
278 OneDTol->SetValue(2,Tol);
280 Handle(TColStd_HArray1OfReal) TwoDTolNul;
281 Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
282 ThreeDTol->Init(Tol/2.);
287 Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C2D, Surf, Tol/20);
289 ResultChron(chr_init, t_init);
292 Standard_Real FirstS = fonct->FirstParameter();
293 Standard_Real LastS = fonct->LastParameter();
295 Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
296 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
297 fonct->Intervals(CutPnts_C2,GeomAbs_C2);
298 Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
299 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
300 fonct->Intervals(CutPnts_C3,GeomAbs_C3);
301 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
304 InitChron(chr_approx);
307 Approx_CurvilinearParameter_EvalCurvOnSurf evCOnS (fonct, FirstS, LastS);
308 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
309 OneDTol, TwoDTolNul, ThreeDTol,
310 FirstS, LastS, Order,
311 MaxDegree, MaxSegments,
315 ResultChron(chr_approx, t_approx);
318 myDone = aApprox.IsDone();
319 myHasResult = aApprox.HasResult();
322 Standard_Integer NbPoles = aApprox.NbPoles();
323 TColgp_Array1OfPnt Poles (1,NbPoles);
324 TColgp_Array1OfPnt2d Poles2d(1,NbPoles);
325 TColStd_Array1OfReal Poles1d(1,NbPoles);
326 aApprox.Poles(1,Poles);
327 aApprox.Poles1d(1,Poles1d);
328 for (i=1; i<=NbPoles; i++)
329 Poles2d(i).SetX(Poles1d(i));
330 aApprox.Poles1d(2,Poles1d);
331 for (i=1; i<=NbPoles; i++)
332 Poles2d(i).SetY(Poles1d(i));
333 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
334 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
335 Standard_Integer Degree = aApprox.Degree();
336 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
337 myCurve2d1 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
339 myMaxError2d1 = Max (aApprox.MaxError(1,1),aApprox.MaxError(1,2));
340 myMaxError3d = aApprox.MaxError(3,1);
343 ResultChron(chr_total, t_total);
345 cout<<" total reparametrization time = "<<t_total<<endl;
346 cout<<"initialization time = "<<t_init<<endl;
347 cout<<"approximation time = "<<t_approx<<endl;
348 cout<<"total time for uparam computation = "<<t_uparam<<endl;
349 cout<<"number uparam calles = "<<uparam_count<<endl;
353 //=======================================================================
354 //function : Approx_CurvilinearParameter_EvalCurvOn2Surf
355 //purpose : case of a curve on two surfaces
356 //=======================================================================
358 class Approx_CurvilinearParameter_EvalCurvOn2Surf : public AdvApprox_EvaluatorFunction
361 Approx_CurvilinearParameter_EvalCurvOn2Surf (const Handle(Approx_CurvlinFunc)& theFunc,
362 Standard_Real First, Standard_Real Last)
363 : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
365 virtual void Evaluate (Standard_Integer *Dimension,
366 Standard_Real StartEnd[2],
367 Standard_Real *Parameter,
368 Standard_Integer *DerivativeRequest,
369 Standard_Real *Result, // [Dimension]
370 Standard_Integer *ErrorCode);
373 Handle(Approx_CurvlinFunc) fonct;
374 Standard_Real StartEndSav[2];
377 void Approx_CurvilinearParameter_EvalCurvOn2Surf::Evaluate (Standard_Integer * Dimension,
378 Standard_Real * StartEnd,
379 Standard_Real * Param,
380 Standard_Integer * Order,
381 Standard_Real * Result,
382 Standard_Integer * ErrorCode)
385 Standard_Real S = *Param;
386 TColStd_Array1OfReal Res(0, 6);
389 // Dimension is incorrect
390 if (*Dimension != 7) {
393 // Parameter is incorrect
394 if ( S < StartEnd[0] || S > StartEnd[1] ) {
398 /* if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1])
400 fonct->Trim(StartEnd[0],StartEnd[1], Precision::Confusion());
401 StartEndSav[0]=StartEnd[0];
402 StartEndSav[1]=StartEnd[1];
405 if(!fonct->EvalCase3(S, *Order, Res)) {
409 for(i = 0; i <= 6; i++)
413 Approx_CurvilinearParameter::Approx_CurvilinearParameter(const Handle(Adaptor2d_HCurve2d)& C2D1,
414 const Handle(Adaptor3d_HSurface)& Surf1,
415 const Handle(Adaptor2d_HCurve2d)& C2D2,
416 const Handle(Adaptor3d_HSurface)& Surf2,
417 const Standard_Real Tol,
418 const GeomAbs_Shape Order,
419 const Standard_Integer MaxDegree,
420 const Standard_Integer MaxSegments)
425 t_total = t_init = t_approx = t_uparam = 0;
427 InitChron(chr_total);
431 // Initialisation of input parameters of AdvApprox
433 Standard_Integer Num1DSS=4, Num2DSS=0, Num3DSS=1;
434 Handle(TColStd_HArray1OfReal) OneDTol = new TColStd_HArray1OfReal(1,Num1DSS);
436 Standard_Real TolV,TolW;
437 ToleranceComputation(C2D1,Surf1,10,Tol,TolV,TolW);
438 OneDTol->SetValue(1,TolV);
439 OneDTol->SetValue(2,TolW);
441 ToleranceComputation(C2D2,Surf2,10,Tol,TolV,TolW);
442 OneDTol->SetValue(3,TolV);
443 OneDTol->SetValue(4,TolW);
445 Handle(TColStd_HArray1OfReal) TwoDTolNul;
446 Handle(TColStd_HArray1OfReal) ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
447 ThreeDTol->Init(Tol/2);
452 Handle(Approx_CurvlinFunc) fonct = new Approx_CurvlinFunc(C2D1, C2D2, Surf1, Surf2, Tol/20);
454 ResultChron(chr_init, t_init);
457 Standard_Real FirstS = fonct->FirstParameter();
458 Standard_Real LastS = fonct->LastParameter();
460 Standard_Integer NbInterv_C2 = fonct->NbIntervals(GeomAbs_C2);
461 TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
462 fonct->Intervals(CutPnts_C2,GeomAbs_C2);
463 Standard_Integer NbInterv_C3 = fonct->NbIntervals(GeomAbs_C3);
464 TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
465 fonct->Intervals(CutPnts_C3,GeomAbs_C3);
466 AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
469 InitChron(chr_approx);
472 Approx_CurvilinearParameter_EvalCurvOn2Surf evCOn2S (fonct, FirstS, LastS);
473 AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
474 OneDTol, TwoDTolNul, ThreeDTol,
475 FirstS, LastS, Order,
476 MaxDegree, MaxSegments,
480 ResultChron(chr_approx, t_approx);
483 myDone = aApprox.IsDone();
484 myHasResult = aApprox.HasResult();
487 Standard_Integer NbPoles = aApprox.NbPoles();
488 TColgp_Array1OfPnt Poles (1,NbPoles);
489 TColgp_Array1OfPnt2d Poles2d(1,NbPoles);
490 TColStd_Array1OfReal Poles1d(1,NbPoles);
491 aApprox.Poles(1,Poles);
492 aApprox.Poles1d(1,Poles1d);
493 for (i=1; i<=NbPoles; i++)
494 Poles2d(i).SetX(Poles1d(i));
495 aApprox.Poles1d(2,Poles1d);
496 for (i=1; i<=NbPoles; i++)
497 Poles2d(i).SetY(Poles1d(i));
498 Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
499 Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
500 Standard_Integer Degree = aApprox.Degree();
501 myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
502 myCurve2d1 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
503 aApprox.Poles1d(3,Poles1d);
504 for (i=1; i<=NbPoles; i++)
505 Poles2d(i).SetX(Poles1d(i));
506 aApprox.Poles1d(4,Poles1d);
507 for (i=1; i<=NbPoles; i++)
508 Poles2d(i).SetY(Poles1d(i));
509 myCurve2d2 = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree);
511 myMaxError2d1 = Max (aApprox.MaxError(1,1),aApprox.MaxError(1,2));
512 myMaxError2d2 = Max (aApprox.MaxError(1,3),aApprox.MaxError(1,4));
513 myMaxError3d = aApprox.MaxError(3,1);
516 ResultChron(chr_total, t_total);
518 cout<<" total reparametrization time = "<<t_total<<endl;
519 cout<<"initialization time = "<<t_init<<endl;
520 cout<<"approximation time = "<<t_approx<<endl;
521 cout<<"total time for uparam computation = "<<t_uparam<<endl;
522 cout<<"number uparam calles = "<<uparam_count<<endl;
526 //=======================================================================
529 //=======================================================================
531 Standard_Boolean Approx_CurvilinearParameter::IsDone() const
536 //=======================================================================
537 //function : HasResult
539 //=======================================================================
541 Standard_Boolean Approx_CurvilinearParameter::HasResult() const
546 //=======================================================================
548 //purpose : returns the Bspline curve corresponding to the reparametrized 3D curve
549 //=======================================================================
551 Handle(Geom_BSplineCurve) Approx_CurvilinearParameter::Curve3d() const
556 //=======================================================================
557 //function : MaxError3d
558 //purpose : returns the maximum error on the reparametrized 3D curve
559 //=======================================================================
561 Standard_Real Approx_CurvilinearParameter::MaxError3d() const
566 //=======================================================================
567 //function : Curve2d1
568 //purpose : returns the BsplineCurve representing the reparametrized 2D curve on the
569 // first surface (case of a curve on one or two surfaces)
570 //=======================================================================
572 Handle(Geom2d_BSplineCurve) Approx_CurvilinearParameter::Curve2d1() const
577 //=======================================================================
578 //function : MaxError2d1
579 //purpose : returns the maximum error on the first reparametrized 2D curve
580 //=======================================================================
582 Standard_Real Approx_CurvilinearParameter::MaxError2d1() const
584 return myMaxError2d1;
587 //=======================================================================
588 //function : Curve2d2
589 //purpose : returns the BsplineCurve representing the reparametrized 2D curve on the
590 // second surface (case of a curve on two surfaces)
591 //=======================================================================
593 Handle(Geom2d_BSplineCurve) Approx_CurvilinearParameter::Curve2d2() const
598 //=======================================================================
599 //function : MaxError2d2
600 //purpose : returns the maximum error on the second reparametrized 2D curve
601 //=======================================================================
603 Standard_Real Approx_CurvilinearParameter::MaxError2d2() const
605 return myMaxError2d2;
608 //=======================================================================
610 //purpose : print the maximum errors(s)
611 //=======================================================================
613 void Approx_CurvilinearParameter::Dump(Standard_OStream& o) const
615 o << "Dump of Approx_CurvilinearParameter" << endl;
616 if (myCase==2 || myCase==3)
617 o << "myMaxError2d1 = " << myMaxError2d1 << endl;
619 o << "myMaxError2d2 = " << myMaxError2d2 << endl;
620 o << "myMaxError3d = " << myMaxError3d << endl;
623 //=======================================================================
624 //function : ToleranceComputation
626 //=======================================================================
628 void Approx_CurvilinearParameter::ToleranceComputation(const Handle(Adaptor2d_HCurve2d) &C2D,
629 const Handle(Adaptor3d_HSurface) &S,
630 const Standard_Integer MaxNumber,
631 const Standard_Real Tol,
632 Standard_Real &TolV, Standard_Real &TolW)
634 Standard_Real FirstU = C2D->FirstParameter(),
635 LastU = C2D->LastParameter();
636 // Standard_Real parU, Max_dS_dv=1.,Max_dS_dw=1.;
637 Standard_Real Max_dS_dv=1.,Max_dS_dw=1.;
642 for (Standard_Integer i=1; i<=MaxNumber; i++) {
643 pntVW = C2D->Value(FirstU + (i-1)*(LastU-FirstU)/(MaxNumber-1));
644 S->D1(pntVW.X(),pntVW.Y(),P,dS_dv,dS_dw);
645 Max_dS_dv = Max (Max_dS_dv, dS_dv.Magnitude());
646 Max_dS_dw = Max (Max_dS_dw, dS_dw.Magnitude());
648 TolV = Tol / (4.*Max_dS_dv);
649 TolW = Tol / (4.*Max_dS_dw);
652 cout << "TolV = " << TolV << endl;
653 cout << "TolW = " << TolW << endl;