0025929: Make Approx_ComputeLine algorithm adaptive
[occt.git] / src / ApproxInt / ApproxInt_Approx.gxx
CommitLineData
b311480e 1// Created on: 1993-03-30
2// Created by: Laurent BUCHARD
3// Copyright (c) 1993-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
17#include <AppParCurves_Constraint.hxx>
18#include <GeomAbs_SurfaceType.hxx>
19#include <IntSurf_Quadric.hxx>
20#include <gp_Trsf.hxx>
21#include <gp_Trsf2d.hxx>
22#include <IntSurf_PntOn2S.hxx>
23#include <Precision.hxx>
f44aa197 24#include <ApproxInt_KnotTools.hxx>
7fd59977 25
26const Standard_Integer LimRajout = 5;
f44aa197 27const Standard_Integer NbPntMaxDecoupage = 30;
28const Standard_Real RatioTol = 1.5;
7fd59977 29
f44aa197 30//=======================================================================
31//function : MINABS3
32//purpose : Compute minimal absolute distance to 0 from 3 values.
33//=======================================================================
34static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c)
35{
7fd59977 36 if(a<0.0) a=-a;
37 if(b<0.0) b=-b;
38 if(c<0.0) c=-c;
39 if(a>c) a=c;
40 if(a>b) a=b;
41 return(a);
42}
43
f44aa197 44//=======================================================================
45//function : MINABS4
46//purpose : Compute minimal absolute distance to 0 from 4 values.
47//=======================================================================
48static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,Standard_Real d)
49{
7fd59977 50 if(a<0.0) a=-a;
51 if(b<0.0) b=-b;
52 if(c<0.0) c=-c;
53 if(d<0.0) d=-d;
54 if(a>c) a=c;
55 if(a>b) a=b;
56 if(a>d) a=d;
57 return(a);
58}
59
f44aa197 60//=======================================================================
61//function : ComputeTrsf3d
62//purpose :
63//=======================================================================
64static void ComputeTrsf3d(const Handle(TheWLine)& theline,
65 Standard_Real& Xo, Standard_Real& Ax,
66 Standard_Real& Yo, Standard_Real& Ay,
67 Standard_Real& Zo, Standard_Real& Az)
68{
69 Standard_Integer nbp = theline->NbPnts();
70 Standard_Real z0,z1,x0,x1,y0,y1;
71 z0=y0=x0=RealLast();
72 z1=y1=x1=RealFirst();
73 for(Standard_Integer i=1;i<=nbp;i++) {
74 const gp_Pnt& P = theline->Point(i).Value();
75 Standard_Real X = P.X();
76 Standard_Real Y = P.Y();
77 Standard_Real Z = P.Z();
78 if(X<x0) x0=X;
79 if(X>x1) x1=X;
80 if(Y<y0) y0=Y;
81 if(Y>y1) y1=Y;
82 if(Z<z0) z0=Z;
83 if(Z>z1) z1=Z;
84 }
85 Standard_Real dx = x1-x0;
86 Standard_Real dy = y1-y0;
87 Standard_Real dz = z1-z0;
88 Standard_Real MaxD = dx;
89 if(MaxD < dy) MaxD=dy;
90 if(MaxD < dz) MaxD=dz;
91 Standard_Real MaxDF = 0.01*MaxD;
92
93 if(MaxDF<1e-12)
94 MaxDF=1.0;
95
96 if(dx > MaxDF) { Ax = 1.0 / dx; Xo = -Ax * x0; }
97 else { Ax = 1.0/( MaxDF) ; Xo = -Ax*x0; }
98 if(dy > MaxDF) { Ay = 1.0 / dy; Yo = -Ay * y0; }
99 else { Ay = 1.0/( MaxDF); Yo = -Ay*y0; }
100 if(dz > MaxDF) { Az = 1.0 / dz; Zo = -Az * z0; }
101 else { Az = 1.0/(MaxDF); Zo = -Az*z0; }
7fd59977 102}
103
f44aa197 104//=======================================================================
105//function : ComputeTrsf2d
106//purpose :
107//=======================================================================
108static void ComputeTrsf2d(const Handle(TheWLine)& theline,
109 Standard_Real& Uo, Standard_Real& Au,
110 Standard_Real& Vo, Standard_Real& Av,
111 const Standard_Boolean onFirst,
112 const Standard_Real UVResRatio = 1.0)
113{
114 Standard_Integer nbp = theline->NbPnts();
115 Standard_Real u0,u1,v0,v1;
116 u0 = v0 = RealLast();
117 u1 = v1 = RealFirst();
118 // pointer to a member-function
119 void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const;
120 if (onFirst)
121 pfunc = &IntSurf_PntOn2S::ParametersOnS1;
122 else
123 pfunc = &IntSurf_PntOn2S::ParametersOnS2;
124 for(Standard_Integer i=1;i<=nbp;i++) {
125 const IntSurf_PntOn2S& POn2S = theline->Point(i);
126 Standard_Real U,V;
127 (POn2S.*pfunc)(U,V);
128 if(U<u0) u0=U;
129 if(U>u1) u1=U;
130 if(V<v0) v0=V;
131 if(V>v1) v1=V;
132 }
7fd59977 133
f44aa197 134 Standard_Real du = (u1-u0);
135 Standard_Real dv = (v1-v0);
7fd59977 136
f44aa197 137 if (UVResRatio > 1.)
138 du *= UVResRatio;
139 else if (UVResRatio < 1.)
140 dv /= UVResRatio;
7fd59977 141
f44aa197 142 Standard_Real MaxUV=du;
143 if(MaxUV<dv) MaxUV=dv;
7fd59977 144
f44aa197 145 Standard_Real MaxUVF=0.01*MaxUV;
7fd59977 146
f44aa197 147 //-- lbr le 22 fev 99 (FPE)
148 if(MaxUVF<1e-12)
149 MaxUVF=1.0;
7fd59977 150
f44aa197 151 if(du > MaxUVF) { Au = 1.0 / du; Uo = -Au * u0; }
152 else { Au = 1.0/(MaxUVF); Uo = -Au*u0; }
153 if(dv > MaxUVF) { Av = 1.0 / dv; Vo = -Av * v0; }
154 else { Av = 1.0/(MaxUVF); Vo = -Av*v0; }
7fd59977 155}
156
f44aa197 157//=======================================================================
158//function : Parameters
159//purpose :
160//=======================================================================
161static void Parameters(const ApproxInt_TheMultiLine& Line,
162 const Standard_Integer firstP,
163 const Standard_Integer lastP,
164 const Approx_ParametrizationType Par,
165 math_Vector& TheParameters)
166{
167 Standard_Integer i, j, nbP2d, nbP3d;
168 Standard_Real dist;
169 gp_Pnt P1, P2;
170 gp_Pnt2d P12d, P22d;
171
172 if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
173 nbP3d = ApproxInt_TheMultiLineTool::NbP3d(Line);
174 nbP2d = ApproxInt_TheMultiLineTool::NbP2d(Line);
175 Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
176 if (nbP3d == 0) mynbP3d = 1;
177 if (nbP2d == 0) mynbP2d = 1;
7fd59977 178
f44aa197 179 TheParameters(firstP) = 0.0;
180 dist = 0.0;
181 TColgp_Array1OfPnt tabP(1, mynbP3d);
182 TColgp_Array1OfPnt tabPP(1, mynbP3d);
183 TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
184 TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
7fd59977 185
f44aa197 186 for (i = firstP+1; i <= lastP; i++) {
187 if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP, tabP2d);
188 else if (nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP2d);
189 else if (nbP3d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP);
190
191 if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP, tabPP2d);
192 else if (nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP2d);
193 else if (nbP3d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP);
194 dist = 0;
195 for (j = 1; j <= nbP3d; j++) {
196 P1 = tabP(j);
197 P2 = tabPP(j);
198 dist += P2.Distance(P1);
199 }
200 for (j = 1; j <= nbP2d; j++) {
201 P12d = tabP2d(j);
202 P22d = tabPP2d(j);
203 dist += P22d.Distance(P12d);
204 }
205 if(Par == Approx_ChordLength)
206 TheParameters(i) = TheParameters(i-1) + dist;
207 else {// Par == Approx_Centripetal
208 TheParameters(i) = TheParameters(i-1) + Sqrt(dist);
209 }
210 }
211 for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
212 }
213 else {
214 for (i = firstP; i <= lastP; i++) {
215 TheParameters(i) = (Standard_Real(i)-firstP)/
216 (Standard_Real(lastP)-Standard_Real(firstP));
217 }
218 }
219}
220
221//=======================================================================
222//function : ApproxInt_Approx
223//purpose : Constructor.
224//=======================================================================
225ApproxInt_Approx::ApproxInt_Approx()
226: myComputeLine(4, 8, 0.001, 0.001, 5, Standard_True),
227 myComputeLineBezier(4, 8, 0.001, 0.001, 5, Standard_True)
228{
7fd59977 229 myComputeLine.SetContinuity(2);
f44aa197 230 myData.myBezierApprox = Standard_True;
231
232 myRelativeTol = Standard_True;
233 myNbPntMax = NbPntMaxDecoupage;
234 myData.myMinFactorXYZ = 0.0;
235 myData.myMinFactorUV = 0.0;
236 myTolReached3d = myTolReached2d = 0.0;
237 myUVRes1 = myUVRes2 = 1.0;
7fd59977 238}
7fd59977 239
f44aa197 240//=======================================================================
241//function : Perform
242//purpose : Build without surfaces information.
243//=======================================================================
7fd59977 244void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline,
f44aa197 245 const Standard_Boolean ApproxXYZ,
246 const Standard_Boolean ApproxU1V1,
247 const Standard_Boolean ApproxU2V2,
248 const Standard_Integer indicemin,
249 const Standard_Integer indicemax)
250{
251 // Prepare DS.
252 prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
253
7fd59977 254 Standard_Integer nbpntbez = indicemax-indicemin;
7fd59977 255 if(nbpntbez < LimRajout)
f44aa197 256 myData.myBezierApprox = Standard_False;
7fd59977 257 else
f44aa197 258 myData.myBezierApprox = Standard_True;
259
260 // Fill data structure.
261 fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
262
263 // Build knots.
264 buildKnots(theline, NULL);
7fd59977 265
f44aa197 266 Standard_Boolean cut = Standard_True;
267 if(myRelativeTol==Standard_False)
268 {
7fd59977 269 myComputeLine.Init(myDegMin,
f44aa197 270 myDegMax,
271 myTol3d*myData.myMinFactorXYZ,
272 myTol2d*myData.myMinFactorUV,
273 myNbIterMax,
274 cut,
275 myData.parametrization);
7fd59977 276 myComputeLineBezier.Init(myDegMin,
f44aa197 277 myDegMax,
278 myTol3d*myData.myMinFactorXYZ,
279 myTol2d*myData.myMinFactorUV,
280 myNbIterMax,
281 cut,
282 myData.parametrization);
7fd59977 283 }
f44aa197 284
285 buildCurve(theline, NULL);
7fd59977 286}
287
f44aa197 288//=======================================================================
289//function : Perform
290//purpose : Param-Param perform.
291//=======================================================================
7fd59977 292void ApproxInt_Approx::Perform(const ThePSurface& Surf1,
f44aa197 293 const ThePSurface& Surf2,
294 const Handle(TheWLine)& theline,
295 const Standard_Boolean ApproxXYZ,
296 const Standard_Boolean ApproxU1V1,
297 const Standard_Boolean ApproxU2V2,
298 const Standard_Integer indicemin,
299 const Standard_Integer indicemax)
300{
7fd59977 301
302 GeomAbs_SurfaceType typeS1 = ThePSurfaceTool::GetType(Surf1);
303 GeomAbs_SurfaceType typeS2 = ThePSurfaceTool::GetType(Surf2);
304 if ((typeS1 != GeomAbs_Plane &&
305 typeS1 != GeomAbs_Cylinder &&
306 typeS1 != GeomAbs_Sphere &&
f44aa197 307 typeS1 != GeomAbs_Cone) &&
7fd59977 308 (typeS2 != GeomAbs_Plane &&
309 typeS2 != GeomAbs_Cylinder &&
310 typeS2 != GeomAbs_Sphere &&
f44aa197 311 typeS2 != GeomAbs_Cone))
312 {
313 // Prepare DS.
314 prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
315
316 // Non-analytical case: Param-Param perform.
7fd59977 317 ApproxInt_ThePrmPrmSvSurfaces myPrmPrmSvSurfaces(Surf1,Surf2);
f44aa197 318
7fd59977 319 Standard_Integer nbpntbez = indicemax-indicemin;
7fd59977 320 if(nbpntbez < LimRajout)
f44aa197 321 myData.myBezierApprox = Standard_False;
7fd59977 322 else
f44aa197 323 myData.myBezierApprox = Standard_True;
324
7fd59977 325 Standard_Boolean cut = Standard_True;
f44aa197 326 if(nbpntbez < LimRajout)
327 {
7fd59977 328 cut = Standard_False;
7fd59977 329 }
7fd59977 330
f44aa197 331 Standard_Real aS1URes = ThePSurfaceTool::UResolution(Surf1, 1.0),
332 aS1VRes = ThePSurfaceTool::VResolution(Surf1, 1.0),
333 aS2URes = ThePSurfaceTool::UResolution(Surf2, 1.0),
334 aS2VRes = ThePSurfaceTool::VResolution(Surf2, 1.0);
335 if(ApproxU1V1)
336 myUVRes1 = aS1URes / aS1VRes;
337 if(ApproxU2V2)
338 myUVRes2 = aS2URes / aS2VRes;
7fd59977 339
f44aa197 340 // Fill data structure.
341 fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
7fd59977 342
f44aa197 343 // Build knots.
344 Standard_Address ptrsvsurf = &myPrmPrmSvSurfaces;
345 buildKnots(theline, ptrsvsurf);
7fd59977 346
f44aa197 347 if(myRelativeTol==Standard_False)
348 {
7fd59977 349 myComputeLine.Init(myDegMin,
f44aa197 350 myDegMax,
351 myTol3d*myData.myMinFactorXYZ,
352 myTol2d*myData.myMinFactorUV,
353 myNbIterMax,
354 cut,
355 myData.parametrization);
7fd59977 356 myComputeLineBezier.Init(myDegMin,
f44aa197 357 myDegMax,
358 myTol3d*myData.myMinFactorXYZ,
359 myTol2d*myData.myMinFactorUV,
360 myNbIterMax,
361 cut,
362 myData.parametrization);
7fd59977 363 }
f44aa197 364 else
365 {
7fd59977 366 myComputeLine.Init(myDegMin,
f44aa197 367 myDegMax,
368 myTol3d,
369 myTol2d,
370 myNbIterMax,
371 cut,
372 myData.parametrization);
7fd59977 373 myComputeLineBezier.Init(myDegMin,
f44aa197 374 myDegMax,
375 myTol3d,
376 myTol2d,
377 myNbIterMax,
378 cut,
379 myData.parametrization);
7fd59977 380 }
381
f44aa197 382 buildCurve(theline, ptrsvsurf);
7fd59977 383 }
f44aa197 384 else
385 {
7fd59977 386 IntSurf_Quadric Quad;
387 Standard_Boolean SecondIsImplicit=Standard_False;
f44aa197 388 switch (typeS1)
389 {
390
7fd59977 391 case GeomAbs_Plane:
392 Quad.SetValue(ThePSurfaceTool::Plane(Surf1));
393 break;
f44aa197 394
7fd59977 395 case GeomAbs_Cylinder:
396 Quad.SetValue(ThePSurfaceTool::Cylinder(Surf1));
397 break;
f44aa197 398
7fd59977 399 case GeomAbs_Sphere:
400 Quad.SetValue(ThePSurfaceTool::Sphere(Surf1));
401 break;
f44aa197 402
7fd59977 403 case GeomAbs_Cone:
404 Quad.SetValue(ThePSurfaceTool::Cone(Surf1));
405 break;
406
407 default:
408 {
f44aa197 409 SecondIsImplicit = Standard_True;
410 switch (typeS2)
411 {
412 case GeomAbs_Plane:
413 Quad.SetValue(ThePSurfaceTool::Plane(Surf2));
414 break;
415
416 case GeomAbs_Cylinder:
417 Quad.SetValue(ThePSurfaceTool::Cylinder(Surf2));
418 break;
419
420 case GeomAbs_Sphere:
421 Quad.SetValue(ThePSurfaceTool::Sphere(Surf2));
422 break;
423
424 case GeomAbs_Cone:
425 Quad.SetValue(ThePSurfaceTool::Cone(Surf2));
426 break;
427
428 default:
429 break;
430 }
7fd59977 431 }
432 break;
433 }
f44aa197 434 if(SecondIsImplicit)
435 {
7fd59977 436 Perform(Surf1,Quad,theline,ApproxXYZ,ApproxU1V1,ApproxU2V2,indicemin,indicemax);
437 }
f44aa197 438 else
439 {
7fd59977 440 Perform(Quad,Surf2,theline,ApproxXYZ,ApproxU1V1,ApproxU2V2,indicemin,indicemax);
441 }
442 }
443}
f44aa197 444
445//=======================================================================
446//function : SetParameters
447//purpose :
448//=======================================================================
7fd59977 449void ApproxInt_Approx::SetParameters(const Standard_Real Tol3d,
f44aa197 450 const Standard_Real Tol2d,
451 const Standard_Integer DegMin,
452 const Standard_Integer DegMax,
453 const Standard_Integer NbIterMax,
454 const Standard_Boolean ApproxWithTangency,
455 const Approx_ParametrizationType Parametrization)
456{
457 myWithTangency = ApproxWithTangency;
458 myTol3d = Tol3d / RatioTol;
459 myTol2d = Tol2d / RatioTol;
460 myDegMin = DegMin;
461 myDegMax = DegMax;
462 myNbIterMax = NbIterMax;
463 myComputeLine.Init(myDegMin,
464 myDegMax,
465 myTol3d,
466 myTol2d,
467 myNbIterMax,
468 Standard_True,
469 Parametrization);
470
471 if(!ApproxWithTangency) {
472 myComputeLine.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
473 }
474 myComputeLineBezier.Init(myDegMin,
475 myDegMax,
476 myTol3d,
477 myTol2d,
478 myNbIterMax,
479 Standard_True,
480 Parametrization);
481 if(!ApproxWithTangency)
482 {
483 myComputeLineBezier.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
484 }
485 myData.myBezierApprox = Standard_True;
7fd59977 486}
487
f44aa197 488//=======================================================================
489//function : SetParameters
490//purpose : Set parameters with RelativeTol flag and NbPntMax value.
491//=======================================================================
7fd59977 492void ApproxInt_Approx::SetParameters(const Standard_Real Tol3d,
f44aa197 493 const Standard_Real Tol2d,
494 const Standard_Boolean RelativeTol,
495 const Standard_Integer DegMin,
496 const Standard_Integer DegMax,
497 const Standard_Integer NbIterMax,
498 const Standard_Integer NbPntMax,
499 const Standard_Boolean ApproxWithTangency,
500 const Approx_ParametrizationType Parametrization)
7fd59977 501{
502 myNbPntMax = NbPntMax ;
503 myRelativeTol = RelativeTol ;
504 SetParameters (Tol3d, Tol2d, DegMin, DegMax, NbIterMax, ApproxWithTangency, Parametrization) ;
505}
506
f44aa197 507//=======================================================================
508//function : Perform
509//purpose : Param-Analytic perform.
510//=======================================================================
7fd59977 511void ApproxInt_Approx::Perform(const ThePSurface& PSurf,
f44aa197 512 const TheISurface& ISurf,
513 const Handle(TheWLine)& theline,
514 const Standard_Boolean ApproxXYZ,
515 const Standard_Boolean ApproxU1V1,
516 const Standard_Boolean ApproxU2V2,
517 const Standard_Integer indicemin,
518 const Standard_Integer indicemax)
7fd59977 519{
f44aa197 520 // Prepare DS.
521 prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
522
523 // Non-analytical case: Param-Analytic perform.
7fd59977 524 ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(PSurf,ISurf);
f44aa197 525
7fd59977 526 Standard_Integer nbpntbez = indicemax-indicemin;
7fd59977 527 if(nbpntbez < LimRajout)
f44aa197 528 myData.myBezierApprox = Standard_False;
7fd59977 529 else
f44aa197 530 myData.myBezierApprox = Standard_True;
531
7fd59977 532 Standard_Boolean cut = Standard_True;
f44aa197 533 if(nbpntbez < LimRajout)
534 {
7fd59977 535 cut = Standard_False;
7fd59977 536 }
537
f44aa197 538 Standard_Real aS1URes = ThePSurfaceTool::UResolution(PSurf, 1.0),
539 aS1VRes = ThePSurfaceTool::VResolution(PSurf, 1.0);
540 if(ApproxU1V1)
541 myUVRes1 = aS1URes / aS1VRes;
7fd59977 542
f44aa197 543 // Fill data structure.
544 fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
7fd59977 545
f44aa197 546 // Build knots.
547 Standard_Address ptrsvsurf = &myImpPrmSvSurfaces;
548 buildKnots(theline, ptrsvsurf);
7fd59977 549
f44aa197 550 if(myRelativeTol==Standard_False)
551 {
7fd59977 552 myComputeLine.Init(myDegMin,
f44aa197 553 myDegMax,
554 myTol3d*myData.myMinFactorXYZ,
555 myTol2d*myData.myMinFactorUV,
556 myNbIterMax,
557 cut,
558 myData.parametrization);
7fd59977 559 myComputeLineBezier.Init(myDegMin,
f44aa197 560 myDegMax,
561 myTol3d*myData.myMinFactorXYZ,
562 myTol2d*myData.myMinFactorUV,
563 myNbIterMax,
564 cut,
565 myData.parametrization);
7fd59977 566 }
f44aa197 567 else
568 {
7fd59977 569 myComputeLine.Init(myDegMin,
f44aa197 570 myDegMax,
571 myTol3d,
572 myTol2d,
573 myNbIterMax,
574 cut,
575 myData.parametrization);
7fd59977 576 myComputeLineBezier.Init(myDegMin,
f44aa197 577 myDegMax,
578 myTol3d,
579 myTol2d,
580 myNbIterMax,
581 cut,
582 myData.parametrization);
7fd59977 583 }
f44aa197 584
585 buildCurve(theline, ptrsvsurf);
7fd59977 586}
f44aa197 587
588//=======================================================================
589//function : Perform
590//purpose : Analytic-Param perform.
591//=======================================================================
7fd59977 592void ApproxInt_Approx::Perform(const TheISurface& ISurf,
f44aa197 593 const ThePSurface& PSurf,
594 const Handle(TheWLine)& theline,
595 const Standard_Boolean ApproxXYZ,
596 const Standard_Boolean ApproxU1V1,
597 const Standard_Boolean ApproxU2V2,
598 const Standard_Integer indicemin,
599 const Standard_Integer indicemax)
7fd59977 600{
f44aa197 601 // Prepare DS.
602 prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
603
604 // Non-analytical case: Analytic-Param perform.
605 ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(ISurf, PSurf);
7fd59977 606
7fd59977 607 Standard_Integer nbpntbez = indicemax-indicemin;
7fd59977 608 if(nbpntbez < LimRajout)
f44aa197 609 myData.myBezierApprox = Standard_False;
7fd59977 610 else
f44aa197 611 myData.myBezierApprox = Standard_True;
612
613 Standard_Boolean cut = Standard_True;
614 if(nbpntbez < LimRajout)
615 {
7fd59977 616 cut = Standard_False;
7fd59977 617 }
f44aa197 618
619 Standard_Real aS2URes = ThePSurfaceTool::UResolution(PSurf, 1.0),
620 aS2VRes = ThePSurfaceTool::VResolution(PSurf, 1.0);
621 if(ApproxU2V2)
622 myUVRes2 = aS2URes / aS2VRes;
623
624 // Fill data structure.
625 fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
626
627 // Build knots.
7c32c7c4 628 Standard_Address ptrsvsurf = &myImpPrmSvSurfaces;
f44aa197 629 buildKnots(theline, ptrsvsurf);
630
631 if(myRelativeTol==Standard_False)
632 {
633 myComputeLine.Init(myDegMin,
634 myDegMax,
635 myTol3d*myData.myMinFactorXYZ,
636 myTol2d*myData.myMinFactorUV,
637 myNbIterMax,
638 cut,
639 myData.parametrization);
640 myComputeLineBezier.Init(myDegMin,
641 myDegMax,
642 myTol3d*myData.myMinFactorXYZ,
643 myTol2d*myData.myMinFactorUV,
644 myNbIterMax,
645 cut,
646 myData.parametrization);
647 }
648 else
649 {
650 myComputeLine.Init(myDegMin,
651 myDegMax,
652 myTol3d,
653 myTol2d,
654 myNbIterMax,
655 cut,
656 myData.parametrization);
657 myComputeLineBezier.Init(myDegMin,
658 myDegMax,
659 myTol3d,
660 myTol2d,
661 myNbIterMax,
662 cut,
663 myData.parametrization);
664 }
665
666 buildCurve(theline, ptrsvsurf);
667}
668
669//=======================================================================
670//function : NbMultiCurves
671//purpose :
672//=======================================================================
673Standard_Integer ApproxInt_Approx::NbMultiCurves() const
674{
675 return 1;
676}
677
678//=======================================================================
679//function : UpdateTolReached
680//purpose :
681//=======================================================================
682void ApproxInt_Approx::UpdateTolReached()
683{
684 if (myData.myBezierApprox)
685 {
686 Standard_Integer ICur;
687 Standard_Integer NbCurves = myComputeLineBezier.NbMultiCurves();
688 for (ICur = 1 ; ICur <= NbCurves ; ICur++)
689 {
690 Standard_Real Tol3D, Tol2D ;
691 myComputeLineBezier.Error (ICur, Tol3D, Tol2D) ;
692 myTolReached3d = Max(myTolReached3d, Tol3D);
693 myTolReached2d = Max(myTolReached2d, Tol2D);
7fd59977 694 }
695 }
f44aa197 696 else
697 {
698 myComputeLine.Error (myTolReached3d, myTolReached2d);
7fd59977 699 }
f44aa197 700}
701
702//=======================================================================
703//function : TolReached3d
704//purpose :
705//=======================================================================
706Standard_Real ApproxInt_Approx::TolReached3d() const
707{
708 Standard_Real TheTol3D = RatioTol * myTolReached3d ;
709
710 if (myData.myMinFactorXYZ>1.5e-7)
711 TheTol3D = TheTol3D / myData.myMinFactorXYZ;
712
713 //cout << "Tol 3D: " << TheTol3D << endl;
714 return TheTol3D ;
715}
716
717//=======================================================================
718//function : TolReached2d
719//purpose :
720//=======================================================================
721Standard_Real ApproxInt_Approx::TolReached2d() const
722{
723 Standard_Real TheTol2D = RatioTol * myTolReached2d ;
724
725 if (myData.myMinFactorUV>1.5e-7)
726 TheTol2D = TheTol2D / myData.myMinFactorUV;
727
728 //cout << "Tol 2D: " << TheTol2D << endl;
729 return TheTol2D ;
730}
731
732//=======================================================================
733//function : IsDone
734//purpose :
735//=======================================================================
736Standard_Boolean ApproxInt_Approx::IsDone() const
737{
738 if(myData.myBezierApprox)
739 {
740 return(myComputeLineBezier.NbMultiCurves() > 0);
741 //-- Lorsque la tolerance n est pas atteinte et qu il
742 //-- faudrait rajouter des points sur la ligne
743 //-- les approx sortent avec la meilleure tolerance
744 //-- atteinte. ( Pas de rajout de points ds cette version)
745 //-- return(myTolReached);
7fd59977 746 }
f44aa197 747 else
748 {
749 return(myComputeLine.IsToleranceReached());
7fd59977 750 }
f44aa197 751}
752
753//=======================================================================
754//function : Value
755//purpose :
756//=======================================================================
757const AppParCurves_MultiBSpCurve& ApproxInt_Approx::Value(const Standard_Integer ) const
758{
759 if(myData.myBezierApprox)
760 {
761 return(myBezToBSpl.Value());
7fd59977 762 }
f44aa197 763 else
764 {
765 return(myComputeLine.Value());
7fd59977 766 }
f44aa197 767}
768
769//=======================================================================
770//function : fillData
771//purpose : Fill ApproxInt data structure.
772//=======================================================================
773void ApproxInt_Approx::fillData(const Handle(TheWLine)& theline,
774 const Standard_Boolean ApproxXYZ,
775 const Standard_Boolean ApproxU1V1,
776 const Standard_Boolean ApproxU2V2)
777{
778 if(ApproxXYZ)
779 {
780 ComputeTrsf3d(theline, myData.Xo, myData.Ax, myData.Yo, myData.Ay, myData.Zo, myData.Az);
7fd59977 781 }
f44aa197 782 else
783 {
784 myData.Xo = myData.Yo = myData.Zo = 0.0;
785 myData.Ax = myData.Ay = myData.Az = 1.0;
7fd59977 786 }
f44aa197 787
788 if(ApproxU1V1)
789 {
790 ComputeTrsf2d(theline, myData.U1o, myData.A1u, myData.V1o, myData.A1v,Standard_True, myUVRes1);
791 }
792 else
793 {
794 myData.U1o = myData.V1o = 0.0;
795 myData.A1u = myData.A1v = 1.0;
796 }
797
798 if(ApproxU2V2)
799 {
800 ComputeTrsf2d(theline, myData.U2o, myData.A2u, myData.V2o, myData.A2v, Standard_False, myUVRes2);
801 }
802 else
803 {
804 myData.U2o = myData.V2o = 0.0;
805 myData.A2u = myData.A2v = 1.0;
806 }
807
808 Standard_Real A3d = MINABS3(myData.Ax, myData.Ay, myData.Az);
809 if((A3d < myData.myMinFactorXYZ) || (myData.myMinFactorXYZ == 0.0))
810 {
811 myData.myMinFactorXYZ = A3d;
812 }
813
814 Standard_Real A2d = MINABS4(myData.A1u, myData.A1v, myData.A2u, myData.A2v);
815 if((A2d < myData.myMinFactorUV) || (myData.myMinFactorUV == 0.0))
816 {
817 myData.myMinFactorUV = A2d;
7fd59977 818 }
f44aa197 819}
820
821//=======================================================================
822//function : prepareDS
823//purpose :
824//=======================================================================
825void ApproxInt_Approx::prepareDS(const Standard_Boolean theApproxXYZ,
826 const Standard_Boolean theApproxU1V1,
827 const Standard_Boolean theApproxU2V2,
828 const Standard_Integer theIndicemin,
829 const Standard_Integer theIndicemax)
830{
831 myData.myMinFactorXYZ = 0.0;
832 myData.myMinFactorUV = 0.0;
833 myTolReached3d = myTolReached2d = 0.0;
834 myUVRes1 = myUVRes2 = 1.0;
835 myData.ApproxU1V1 = theApproxU1V1;
836 myData.ApproxU2V2 = theApproxU2V2;
837 myData.ApproxXYZ = theApproxXYZ;
838 myData.indicemin = theIndicemin;
839 myData.indicemax = theIndicemax;
840 myData.nbpntmax = myNbPntMax;
7fd59977 841
842 Approx_ParametrizationType parametrization;
843 myComputeLineBezier.Parametrization(parametrization);
f44aa197 844 myData.parametrization = parametrization;
845}
846
847//=======================================================================
848//function : buildKnots
849//purpose :
850//=======================================================================
851void ApproxInt_Approx::buildKnots(const Handle(TheWLine)& theline,
852 const Standard_Address thePtrSVSurf)
853{
854 myKnots.Clear();
855 if(myData.myBezierApprox)
856 {
857 ApproxInt_TheMultiLine aTestLine(theline,
858 thePtrSVSurf,
859 ((myData.ApproxXYZ)? 1 : 0),
860 ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
861 myData.Xo, myData.Ax, myData.Yo, myData.Ay, myData.Zo, myData.Az,
862 myData.U1o, myData.A1u,
863 myData.V1o, myData.A1v,
864 myData.U2o, myData.A2u,
865 myData.V2o ,myData.A2v,
866 myData.ApproxU1V1,
867 myData.indicemin,
868 myData.indicemax);
869
870 Standard_Integer nbp3d = aTestLine.NbP3d();
871 Standard_Integer nbp2d = aTestLine.NbP2d();
872 TColgp_Array1OfPnt aTabPnt3d(1, Max(1, nbp3d));
873 TColgp_Array1OfPnt2d aTabPnt2d(1, Max(1, nbp2d));
874 TColgp_Array1OfPnt aPntXYZ(myData.indicemin, myData.indicemax);
875 TColgp_Array1OfPnt2d aPntU1V1(myData.indicemin, myData.indicemax);
876 TColgp_Array1OfPnt2d aPntU2V2(myData.indicemin, myData.indicemax);
877 Standard_Integer i;
878 for(i = myData.indicemin; i <= myData.indicemax; ++i)
879 {
880 if (nbp3d != 0 && nbp2d != 0) aTestLine.Value(i, aTabPnt3d, aTabPnt2d);
881 else if (nbp2d != 0) aTestLine.Value(i, aTabPnt2d);
882 else if (nbp3d != 0) aTestLine.Value(i, aTabPnt3d);
883 //
884 if(nbp3d > 0)
885 {
886 aPntXYZ(i) = aTabPnt3d(1);
887 }
888 if(nbp2d > 1)
889 {
890 aPntU1V1(i) = aTabPnt2d(1);
891 aPntU2V2(i) = aTabPnt2d(2);
892 }
893 else if(nbp2d > 0)
894 {
895 if(myData.ApproxU1V1)
896 {
897 aPntU1V1(i) = aTabPnt2d(1);
898 }
899 else
900 {
901 aPntU2V2(i) = aTabPnt2d(1);
902 }
903 }
904 }
905
906 Standard_Integer aMinNbPnts = myData.nbpntmax;
907
908 // Expected parametrization.
909 math_Vector aPars(myData.indicemin, myData.indicemax);
910 Parameters(aTestLine, myData.indicemin, myData.indicemax, myData.parametrization, aPars);
911
912 ApproxInt_KnotTools::BuildKnots(aPntXYZ, aPntU1V1, aPntU2V2, aPars,
913 myData.ApproxXYZ, myData.ApproxU1V1, myData.ApproxU2V2, aMinNbPnts, myKnots);
914 }
915 else
916 {
917 myKnots.Append(myData.indicemin);
918 myKnots.Append(myData.indicemax);
919 }
920}
921
922//=======================================================================
923//function : buildCurve
924//purpose :
925//=======================================================================
926void ApproxInt_Approx::buildCurve(const Handle(TheWLine)& theline,
927 const Standard_Address thePtrSVSurf)
928{
929 if(myData.myBezierApprox)
930 {
931 myBezToBSpl.Reset();
7fd59977 932 }
7c32c7c4 933
f44aa197 934 Standard_Integer kind = myKnots.Lower();
935 Standard_Integer imin, imax;
936 myTolReached = Standard_True;
937 Standard_Boolean OtherInter = Standard_False;
938 do
939 {
940 // Base cycle: iterate over knots.
941 imin = myKnots(kind);
942 imax = myKnots(kind+1);
943 ApproxInt_TheMultiLine myMultiLine(theline,
944 thePtrSVSurf,
945 ((myData.ApproxXYZ)? 1 : 0),
946 ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
947 myData.Xo, myData.Ax, myData.Yo,myData.Ay, myData.Zo,myData.Az,
948 myData.U1o, myData.A1u, myData.V1o, myData.A1v,
949 myData.U2o, myData.A2u, myData.V2o, myData.A2v,
950 myData.ApproxU1V1,
951 imin,
952 imax);
7c32c7c4 953
f44aa197 954 if(myData.myBezierApprox)
955 {
956 myComputeLineBezier.Perform(myMultiLine);
7fd59977 957 if (myComputeLineBezier.NbMultiCurves() == 0)
f44aa197 958 return;
7fd59977 959 myTolReached&=myComputeLineBezier.IsToleranceReached();
960 }
f44aa197 961 else
962 {
7fd59977 963 myComputeLine.Perform(myMultiLine);
964 }
965 UpdateTolReached();
f44aa197 966
7fd59977 967 Standard_Integer indice3d,indice2d1,indice2d2;
968 indice3d = 1;
969 indice2d1= 2;
970 indice2d2= 3;
f44aa197 971 if(!myData.ApproxXYZ) { indice2d1--; indice2d2--; }
972 if(!myData.ApproxU1V1) { indice2d2--; }
973 if(myData.ApproxXYZ)
974 {
7fd59977 975 Standard_Real ax,bx,ay,by,az,bz;
f44aa197 976 ax = 1.0/myData.Ax; bx = -myData.Xo*ax;
977 ay = 1.0/myData.Ay; by = -myData.Yo*ay;
978 az = 1.0/myData.Az; bz = -myData.Zo*az;
979 if(myData.myBezierApprox)
980 {
981 for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
982 {
983 myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az);
984 }
7fd59977 985 }
f44aa197 986 else
987 {
988 myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az);
7fd59977 989 }
990 }
f44aa197 991 if(myData.ApproxU1V1)
992 {
7fd59977 993 Standard_Real ax,bx,ay,by;
f44aa197 994 ax = 1.0/myData.A1u; bx = -myData.U1o*ax;
995 ay = 1.0/myData.A1v; by = -myData.V1o*ay;
996 if(myData.myBezierApprox) {
997 for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
998 {
999 myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay);
1000 }
7fd59977 1001 }
f44aa197 1002 else
1003 {
1004 myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay);
7fd59977 1005 }
1006 }
f44aa197 1007 if(myData.ApproxU2V2)
1008 {
7fd59977 1009 Standard_Real ax,bx,ay,by;
f44aa197 1010 ax = 1.0/myData.A2u; bx = -myData.U2o*ax;
1011 ay = 1.0/myData.A2v; by = -myData.V2o*ay;
1012 if(myData.myBezierApprox)
1013 {
1014 for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
1015 {
1016 myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay);
1017 }
7fd59977 1018 }
f44aa197 1019 else
1020 {
1021 myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay);
7fd59977 1022 }
1023 }
f44aa197 1024
7fd59977 1025 OtherInter = Standard_False;
f44aa197 1026 if(myData.myBezierApprox)
0cbfb9f1 1027 {
f44aa197 1028 for(Standard_Integer nbmc = 1;
1029 nbmc <= myComputeLineBezier.NbMultiCurves();
0cbfb9f1 1030 nbmc++)
f44aa197 1031 {
0cbfb9f1 1032 myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
7fd59977 1033 }
f44aa197 1034 kind++;
1035 if(kind < myKnots.Upper())
0cbfb9f1 1036 {
0cbfb9f1 1037 OtherInter = Standard_True;
7fd59977 1038 }
0cbfb9f1 1039 }
7fd59977 1040 }
f44aa197 1041 while(OtherInter);
0cbfb9f1 1042
f44aa197 1043 if(myData.myBezierApprox)
0cbfb9f1 1044 {
f44aa197 1045 myBezToBSpl.Perform();
0cbfb9f1 1046 }
f44aa197 1047}