0028486: Fuse of several solids fails due to presence of common zones between faces
[occt.git] / src / ProjLib / ProjLib_ComputeApprox.cxx
CommitLineData
b311480e 1// Created on: 1993-09-07
2// Created by: Bruno DUMORTIER
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.
b311480e 16
7fd59977 17// modified by NIZHNY-OFV Thu Jan 20 11:04:19 2005
18
19#include <ProjLib_ComputeApprox.hxx>
20
21#include <GeomAbs_SurfaceType.hxx>
22#include <GeomAbs_CurveType.hxx>
368cdde6 23#include <AppCont_Function.hxx>
7fd59977 24#include <Convert_CompBezierCurves2dToBSplineCurve2d.hxx>
25#include <ElSLib.hxx>
26#include <ElCLib.hxx>
27#include <BSplCLib.hxx>
28#include <Standard_NoSuchObject.hxx>
29#include <Geom_UndefinedDerivative.hxx>
30#include <gp.hxx>
31#include <gp_Trsf.hxx>
32#include <Precision.hxx>
33#include <Approx_FitAndDivide2d.hxx>
34#include <AppParCurves_MultiCurve.hxx>
7fd59977 35#include <Adaptor3d_HCurve.hxx>
7fd59977 36#include <Adaptor3d_HSurface.hxx>
37#include <TColgp_Array1OfPnt2d.hxx>
38#include <TColgp_Array1OfPnt.hxx>
39#include <TColStd_Array1OfReal.hxx>
40#include <TColStd_Array1OfInteger.hxx>
41#include <Geom_BSplineCurve.hxx>
42#include <Geom_BezierCurve.hxx>
43#include <Geom2d_BSplineCurve.hxx>
44#include <Geom2d_BezierCurve.hxx>
0a40a30d 45#include <GCPnts_AbscissaPoint.hxx>
7fd59977 46
8e007da7 47//#define DRAW
7fd59977 48#ifdef DRAW
49#include <DrawTrSurf.hxx>
50#endif
0797d9d3 51#ifdef OCCT_DEBUG
76363522 52//static Standard_Boolean AffichValue = Standard_False;
7fd59977 53#endif
54
7fd59977 55//=======================================================================
56//function : IsEqual
57//purpose :
58//=======================================================================
59// OFV:
60static inline Standard_Boolean IsEqual(Standard_Real Check,Standard_Real With,Standard_Real Toler)
61{
62 return ((Abs(Check - With) < Toler) ? Standard_True : Standard_False);
63}
64
65
66//=======================================================================
67//function : Value
68//purpose :
69//=======================================================================
70
71static gp_Pnt2d Function_Value(const Standard_Real U,
72 const Handle(Adaptor3d_HCurve)& myCurve,
73 const Handle(Adaptor3d_HSurface)& mySurface,
74 const Standard_Real U1,
75 const Standard_Real U2,
76 const Standard_Real V1,
77 const Standard_Real V2,
78 const Standard_Boolean UCouture,
79 const Standard_Boolean VCouture )
80{
1d47d8d0 81 Standard_Real S = 0., T = 0.;
7fd59977 82
83 gp_Pnt P3d = myCurve->Value(U);
84 GeomAbs_SurfaceType SType = mySurface->GetType();
85
86 switch ( SType ) {
87
88 case GeomAbs_Plane:
89 {
90 gp_Pln Plane = mySurface->Plane();
91 ElSLib::Parameters( Plane, P3d, S, T);
92 break;
93 }
94 case GeomAbs_Cylinder:
95 {
96 gp_Cylinder Cylinder = mySurface->Cylinder();
97 ElSLib::Parameters( Cylinder, P3d, S, T);
98 break;
99 }
100 case GeomAbs_Cone:
101 {
102 gp_Cone Cone = mySurface->Cone();
103 ElSLib::Parameters( Cone, P3d, S, T);
104 break;
105 }
106 case GeomAbs_Sphere:
107 {
108 gp_Sphere Sphere = mySurface->Sphere();
109 ElSLib::Parameters(Sphere, P3d, S, T);
110 break;
111 }
112 case GeomAbs_Torus:
113 {
114 gp_Torus Torus = mySurface->Torus();
115 ElSLib::Parameters( Torus, P3d, S, T);
116 break;
117 }
118 default:
9775fa61 119 throw Standard_NoSuchObject("ProjLib_ComputeApprox::Value");
7fd59977 120 }
121
122 if ( UCouture) {
ef2d8af7 123 if(S < U1 || S > U2)
368cdde6 124 {
125 S = ElCLib::InPeriod(S, U1, U2);
126 }
7fd59977 127 }
128
129 if ( VCouture) {
130 if(SType == GeomAbs_Sphere) {
c6541a0c 131 if ( Abs( S - U1 ) > M_PI ) {
ef2d8af7 132 T = M_PI - T;
133 S = M_PI + S;
7fd59977 134 }
ef2d8af7 135 if(S > U1 || S < U2)
136 S = ElCLib::InPeriod(S, U1, U2);
7fd59977 137 }
ef2d8af7 138 if(T < V1 || T > V2)
139 T = ElCLib::InPeriod(T, V1, V2);
7fd59977 140 }
6f7c5420 141
7fd59977 142 return gp_Pnt2d(S, T);
143}
144//=======================================================================
145//function : D1
146//purpose :
147//=======================================================================
148static Standard_Boolean Function_D1( const Standard_Real U,
149 gp_Pnt2d& P,
150 gp_Vec2d& D,
151 const Handle(Adaptor3d_HCurve)& myCurve,
152 const Handle(Adaptor3d_HSurface)& mySurface,
153 const Standard_Real U1,
154 const Standard_Real U2,
155 const Standard_Real V1,
156 const Standard_Real V2,
157 const Standard_Boolean UCouture,
158 const Standard_Boolean VCouture )
159{
160 gp_Pnt P3d;
161 Standard_Real dU, dV;
162
163 P = Function_Value(U,myCurve,mySurface,U1,U2,V1,V2,UCouture,VCouture);
164
165 GeomAbs_SurfaceType Type = mySurface->GetType();
166
167 switch ( Type) {
168 case GeomAbs_Plane:
169 case GeomAbs_Cone:
170 case GeomAbs_Cylinder:
171 case GeomAbs_Sphere:
172 case GeomAbs_Torus:
173 {
174 gp_Vec D1U, D1V;
175 gp_Vec T;
176 myCurve->D1(U,P3d,T);
177 mySurface->D1(P.X(),P.Y(),P3d,D1U,D1V);
178
179 dU = T.Dot(D1U);
180 dV = T.Dot(D1V);
181 Standard_Real Nu = D1U.SquareMagnitude();
182 Standard_Real Nv = D1V.SquareMagnitude();
183
184 if ( Nu < Epsilon(1.) || Nv < Epsilon(1.))
ef2d8af7 185 return Standard_False;
7fd59977 186
187 dU /= Nu;
188 dV /= Nv;
189 D = gp_Vec2d( dU, dV);
190 }
191 break;
192
193 default:
194 return Standard_False;
195 }
196
197 return Standard_True;
198}
0a40a30d 199//=======================================================================
200//function : Function_ComputeStep
201//purpose :
202//=======================================================================
203static Standard_Real Function_ComputeStep(
204 const Handle(Adaptor3d_HCurve)& myCurve,
205 const Standard_Real R)
206{
207 Standard_Real Step0 = .1;
208 Standard_Real W1, W2;
209 W1 = myCurve->FirstParameter();
210 W2 = myCurve->LastParameter();
211 Standard_Real L = GCPnts_AbscissaPoint::Length(myCurve->Curve());
212 Standard_Integer nbp = RealToInt(L / (R*M_PI_4)) + 1;
213 nbp = Max(nbp, 3);
214 Standard_Real Step = (W2 - W1) / (nbp - 1);
215 if (Step > Step0)
216 {
217 Step = Step0;
218 nbp = RealToInt((W2 - W1) / Step) + 1;
219 nbp = Max(nbp, 3);
220 Step = (W2 - W1) / (nbp - 1);
221 }
222
223 return Step;
7fd59977 224
0a40a30d 225}
7fd59977 226//=======================================================================
227//function : Function_SetUVBounds
228//purpose :
229//=======================================================================
230static void Function_SetUVBounds(Standard_Real& myU1,
231 Standard_Real& myU2,
232 Standard_Real& myV1,
233 Standard_Real& myV2,
234 Standard_Boolean& UCouture,
235 Standard_Boolean& VCouture,
236 const Handle(Adaptor3d_HCurve)& myCurve,
237 const Handle(Adaptor3d_HSurface)& mySurface)
238{
239 Standard_Real W1, W2, W;
240 gp_Pnt P1, P2, P;
241 //
242 W1 = myCurve->FirstParameter();
243 W2 = myCurve->LastParameter ();
244 W = 0.5*(W1+W2);
245 // on ouvre l`intervalle
246 // W1 += 1.0e-9;
247 // W2 -= 1.0e-9;
248 P1 = myCurve->Value(W1);
249 P2 = myCurve->Value(W2);
250 P = myCurve->Value(W);
251
252 switch ( mySurface->GetType()) {
253
ef2d8af7 254 case GeomAbs_Cone: {
8f8398f6 255 Standard_Real tol = Epsilon(1.);
256 Standard_Real ptol = Precision::PConfusion();
ef2d8af7 257 gp_Cone Cone = mySurface->Cone();
258 VCouture = Standard_False;
8f8398f6 259 //Calculation of cone parameters for P == ConeApex often produces wrong
260 //values of U
261 gp_Pnt ConeApex = Cone.Apex();
262 if(ConeApex.XYZ().IsEqual(P1.XYZ(), tol))
263 {
264 W1 += ptol;
265 P1 = myCurve->Value(W1);
266 }
267 if(ConeApex.XYZ().IsEqual(P2.XYZ(), tol))
268 {
269 W2 -= ptol;
270 P2 = myCurve->Value(W2);
271 }
272 if(ConeApex.XYZ().IsEqual(P.XYZ(), tol))
273 {
274 W += ptol;
275 P = myCurve->Value(W);
276 }
ef2d8af7 277
278 switch( myCurve->GetType() ){
279 case GeomAbs_Parabola:
280 case GeomAbs_Hyperbola:
281 case GeomAbs_Ellipse:{
282 Standard_Real U1, U2, V1, V2, U , V;
283 ElSLib::Parameters( Cone, P1, U1, V1);
284 ElSLib::Parameters( Cone, P2, U2, V2);
285 ElSLib::Parameters( Cone, P , U , V );
286 myU1 = Min(U1,U2);
287 myU2 = Max(U1,U2);
288 if ( ( U1 < U && U < U2 ) && !myCurve->IsClosed() ) {
289 UCouture = Standard_False;
290 }
291 else {
292 UCouture = Standard_True;
293 myU2 = myU1 + 2*M_PI;
294 }
295
7fd59977 296 }
7fd59977 297 break;
ef2d8af7 298 default: {
299 Standard_Real U1, V1, U , V, Delta = 0., d = 0., pmin = W1, pmax = W1, dmax = 0., Uf, Ul;
300 ElSLib::Parameters( Cone, P1, U1, V1);
301 ElSLib::Parameters( Cone, P2, Ul, V1);
0a40a30d 302 const gp_Ax1& anAx1 = Cone.Axis();
303 gp_Lin aLin(anAx1);
304 Standard_Real R = (aLin.Distance(P1) + aLin.Distance(P2) + aLin.Distance(P)) / 3.;
305 Standard_Real Step;
306 myU1 = U1; myU2 = U1; Uf = U1;
307 if (myCurve->GetType() == GeomAbs_Line)
8f8398f6 308 {
0a40a30d 309 Standard_Integer nbp = 3;
310 Step = (W2 - W1) / (nbp - 1);
8f8398f6 311 }
0a40a30d 312 else
313 {
314 Step = Function_ComputeStep(myCurve, R);
315 }
316 //
ef2d8af7 317 Standard_Boolean isclandper = (!(myCurve->IsClosed()) && !(myCurve->IsPeriodic()));
4e14c88f 318 Standard_Boolean isFirst = Standard_True;
319 for(Standard_Real par = W1 + Step; par <= W2; par += Step)
320 {
ef2d8af7 321 if(!isclandper) par += Step;
322 P = myCurve->Value(par);
323 ElSLib::Parameters( Cone, P, U, V);
324 U += Delta;
325 d = U - U1;
4e14c88f 326 if(d > M_PI)
327 {
ef2d8af7 328 if( ( (IsEqual(U,(2*M_PI),1.e-10) && (U1 >= 0. && U1 <= M_PI)) &&
4e14c88f 329 (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,0.,1.e-10)) ) && isclandper )
330 U = 0.0;
331 else
332 {
333 // Protection against first-last point on seam.
334 if (isFirst)
335 U1 = 2*M_PI;
336 else if (par + Step >= W2)
337 U = 0.0;
338 else
339 Delta -= 2*M_PI;
340 }
ef2d8af7 341 U += Delta;
342 d = U - U1;
343 }
4e14c88f 344 else if(d < -M_PI)
345 {
ef2d8af7 346 if( ( (IsEqual(U,0.,1.e-10) && (U1 >= M_PI && U1 <= (2*M_PI))) &&
4e14c88f 347 (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,(2*M_PI),1.e-10)) ) && isclandper )
348 U = 2*M_PI;
349 else
350 {
351 // Protection against first-last point on seam.
352 if (isFirst)
353 U1 = 0.0;
354 else if (par + Step >= W2)
355 U = 2*M_PI;
356 else
357 Delta += 2*M_PI;
358 }
ef2d8af7 359 U += Delta;
360 d = U - U1;
361 }
362 dmax = Max(dmax, Abs(d));
363 if(U < myU1) {myU1 = U; pmin = par;}
364 if(U > myU2) {myU2 = U; pmax = par;}
365 U1 = U;
4e14c88f 366 isFirst = Standard_False;
367 } // for(Standard_Real par = W1 + Step; par <= W2; par += Step)
ef2d8af7 368
369 if(!(Abs(pmin - W1) <= Precision::PConfusion() || Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
370 if(!(Abs(pmax - W1) <= Precision::PConfusion() || Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
371
372 if((myU1 >=0. && myU1 <= 2*M_PI) && (myU2 >=0. && myU2 <= 2*M_PI) ) UCouture = Standard_False;
373 else{
374 U = ( myU1 + myU2 ) /2.;
375 myU1 = U - M_PI;
376 myU2 = U + M_PI;
377 UCouture = Standard_True;
378 }
7fd59977 379 }
7fd59977 380 break;
381 }// switch curve type
382 }// case Cone
ef2d8af7 383 break;
384
7fd59977 385 case GeomAbs_Cylinder: {
386 gp_Cylinder Cylinder = mySurface->Cylinder();
387 VCouture = Standard_False;
ef2d8af7 388
7fd59977 389 if (myCurve->GetType() == GeomAbs_Ellipse) {
ef2d8af7 390
7fd59977 391 Standard_Real U1, U2, V1, V2, U , V;
392 ElSLib::Parameters( Cylinder, P1, U1, V1);
393 ElSLib::Parameters( Cylinder, P2, U2, V2);
394 ElSLib::Parameters( Cylinder, P , U , V );
395 myU1 = Min(U1,U2);
396 myU2 = Max(U1,U2);
ef2d8af7 397
7fd59977 398 if ( !myCurve->IsClosed()) {
ef2d8af7 399 if ( myU1 < U && U < myU2) {
400 U = ( myU1 + myU2 ) /2.;
401 myU1 = U - M_PI;
402 myU2 = U + M_PI;
403 }
404 else {
405 U = ( myU1 + myU2 ) /2.;
406 if ( myU1 < U) {
407 myU1 = U - 2*M_PI;
408 myU2 = U;
409 }
410 else {
411 myU1 = U;
412 myU2 = U + 2*M_PI;
413 }
414 }
415 UCouture = Standard_True;
7fd59977 416 }
417 else {
ef2d8af7 418 gp_Vec D1U, D1V;
419 gp_Vec T;
420 gp_Pnt P3d;
421 myCurve->D1(W1,P3d,T);
422 mySurface->D1(U1,U2,P3d,D1U,D1V);
423 Standard_Real dU = T.Dot(D1U);
424
425 UCouture = Standard_True;
426 if ( dU > 0.) {
427 myU2 = myU1 + 2*M_PI;
428 }
429 else {
430 myU2 = myU1;
431 myU1 -= 2*M_PI;
432 }
7fd59977 433 }
434 }
435 else {
436 Standard_Real U1, V1, U , V;
437 ElSLib::Parameters( Cylinder, P1, U1, V1);
0a40a30d 438 Standard_Real R = Cylinder.Radius();
439 Standard_Real Delta = 0., Step;
c6541a0c 440 Standard_Real eps = M_PI, dmax = 0., d = 0.;
0a40a30d 441 Step = Function_ComputeStep(myCurve, R);
7fd59977 442 myU1 = U1; myU2 = U1;
443 Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step;
444 for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
ef2d8af7 445 P = myCurve->Value(par);
446 ElSLib::Parameters( Cylinder, P, U, V);
447 U += Delta;
448 d = U - U1;
449 if(d > eps) {
450 U -= Delta;
451 Delta -= 2*M_PI;
452 U += Delta;
453 d = U - U1;
454 }
455 else if(d < -eps) {
456 U -= Delta;
457 Delta += 2*M_PI;
458 U += Delta;
459 d = U - U1;
460 }
461 dmax = Max(dmax, Abs(d));
462 if(U < myU1) {myU1 = U; pmin = par;}
463 if(U > myU2) {myU2 = U; pmax = par;}
464 U1 = U;
7fd59977 465 }
ef2d8af7 466
7fd59977 467 if(!(Abs(pmin - W1) <= Precision::PConfusion() ||
ef2d8af7 468 Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
7fd59977 469 if(!(Abs(pmax - W1) <= Precision::PConfusion() ||
ef2d8af7 470 Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
471
c6541a0c 472 if((myU1 >=0. && myU1 <= 2*M_PI) &&
ef2d8af7 473 (myU2 >=0. && myU2 <= 2*M_PI) ) {
474 UCouture = Standard_False;
7fd59977 475 }
476 else {
ef2d8af7 477 U = ( myU1 + myU2 ) /2.;
478 myU1 = U - M_PI;
479 myU2 = U + M_PI;
480 UCouture = Standard_True;
7fd59977 481 }
482 }
483 }
ef2d8af7 484 break;
485 //
7fd59977 486 case GeomAbs_Sphere:{
487 VCouture = Standard_False;
488 gp_Sphere SP = mySurface->Sphere();
489 if ( myCurve->GetType() == GeomAbs_Circle) {
490 UCouture = Standard_True;
ef2d8af7 491
7fd59977 492 // on cherche a savoir le nombre de fois que la couture est
493 // traversee.
494 // si 0 ou 2 fois : la PCurve est fermee et dans l`intervalle
495 // [Uc-PI, Uc+PI] (Uc: U du centre du cercle)
496 // si 1 fois : la PCurve est ouverte et dans l`intervalle
497 // [U1, U1 +/- 2*PI]
498
499 // pour determiner le nombre de solution, on resoud le systeme
500 // x^2 + y^2 + z^2 = R^2 (1)
501 // A x + B y + C z + D = 0 (2)
502 // x > 0 (3)
503 // y = 0 (4)
504 // REM : (1) (2) : equation du cercle
505 // (1) (3) (4) : equation de la couture.
506 Standard_Integer NbSolutions = 0;
507 Standard_Real A, B, C, D, R, Tol = 1.e-10;
96a95605 508 Standard_Real U1, U2, V1, V2;
7fd59977 509 gp_Trsf Trsf;
510 //
7fd59977 511 gp_Circ Circle = myCurve->Circle();
512 Trsf.SetTransformation(SP.Position());
513 Circle.Transform(Trsf);
514 //
515 R = SP.Radius();
516 gp_Pln Plane( gp_Ax3(Circle.Position()));
517 Plane.Coefficients(A,B,C,D);
518 //
519 if ( Abs(C) < Tol) {
ef2d8af7 520 if ( Abs(A) > Tol) {
521 if ( (D/A) < 0.) {
522 if ( ( R - Abs(D/A)) > Tol) NbSolutions = 2;
523 else if ( Abs(R - Abs(D/A))< Tol) NbSolutions = 1;
524 else NbSolutions = 0;
525 }
526 }
7fd59977 527 }
528 else {
ef2d8af7 529 Standard_Real delta = R*R*(A*A+C*C) - D*D;
530 delta *= C*C;
531 if ( Abs(delta) < Tol*Tol) {
532 if ( A*D > 0.) NbSolutions = 1;
533 }
534 else if ( delta > 0) {
535 Standard_Real xx;
536 delta = Sqrt(delta);
537 xx = -A*D+delta;
538 //
539 if ( xx > Tol) NbSolutions++;
540 xx = -A*D-delta;
541 //
542 if ( xx > Tol) NbSolutions++;
543 }
7fd59977 544 }
545 //
546
547 // box+sphere >>
548 Standard_Real UU = 0.;
549 ElSLib::Parameters(SP, P1, U1, V1);
8e007da7 550 Standard_Real eps = 10.*Epsilon(1.);
ef2d8af7 551 Standard_Real dt = Max(Precision::PConfusion(), 0.01*(W2-W1));
552 if(Abs(U1) < eps)
553 {
554 //May be U1 must be equal 2*PI?
555 gp_Pnt Pd = myCurve->Value(W1+dt);
556 Standard_Real ud, vd;
557 ElSLib::Parameters(SP, Pd, ud, vd);
558 if(Abs(U1 - ud) > M_PI)
559 {
560 U1 = 2.*M_PI;
561 }
562 }
563 else if(Abs(2.*M_PI - U1) < eps)
564 {
565 //maybe U1 = 0.?
566 gp_Pnt Pd = myCurve->Value(W1+dt);
567 Standard_Real ud, vd;
568 ElSLib::Parameters(SP, Pd, ud, vd);
569 if(Abs(U1 - ud) > M_PI)
570 {
571 U1 = 0.;
572 }
573 }
574 //
7fd59977 575 ElSLib::Parameters(SP, P2, U2, V1);
ef2d8af7 576 if(Abs(U2) < eps)
577 {
578 //May be U2 must be equal 2*PI?
579 gp_Pnt Pd = myCurve->Value(W2-dt);
580 Standard_Real ud, vd;
581 ElSLib::Parameters(SP, Pd, ud, vd);
582 if(Abs(U2 - ud) > M_PI)
583 {
584 U2 = 2.*M_PI;
585 }
586 }
587 else if(Abs(2.*M_PI - U2) < eps)
588 {
589 //maybe U2 = 0.?
590 gp_Pnt Pd = myCurve->Value(W2-dt);
591 Standard_Real ud, vd;
592 ElSLib::Parameters(SP, Pd, ud, vd);
593 if(Abs(U2 - ud) > M_PI)
594 {
595 U2 = 0.;
596 }
597 }
598 //
7fd59977 599 ElSLib::Parameters(SP, P, UU, V1);
6f7c5420 600 //+This fragment was the reason of bug # 26008.
601 //+It has been deleted on April, 03 2015.
602 //Standard_Real UUmi = Min(Min(U1,UU),Min(UU,U2));
603 //Standard_Real UUma = Max(Max(U1,UU),Max(UU,U2));
604 //Standard_Boolean reCalc = ((UUmi >= 0. && UUmi <= M_PI) && (UUma >= 0. && UUma <= M_PI));
7fd59977 605 // box+sphere <<
c6541a0c 606 P2 = myCurve->Value(W1+M_PI/8);
7fd59977 607 ElSLib::Parameters(SP,P2,U2,V2);
608 //
609 if ( NbSolutions == 1) {
ef2d8af7 610 if ( Abs(U1-U2) > M_PI) { // on traverse la couture
611 if ( U1 > M_PI) {
612 myU1 = U1;
613 myU2 = U1+2*M_PI;
614 }
615 else {
616 myU2 = U1;
617 myU1 = U1-2*M_PI;
618 }
619 }
620 else { // on ne traverse pas la couture
621 if ( U1 > U2) {
622 myU2 = U1;
623 myU1 = U1-2*M_PI;
624 }
625 else {
626 myU1 = U1;
627 myU2 = U1+2*M_PI;
628 }
629 }
7fd59977 630 }
631 else { // 0 ou 2 solutions
ef2d8af7 632 gp_Pnt Center = Circle.Location();
633 Standard_Real U,V;
634 ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
635 myU1 = U-M_PI;
636 myU2 = U+M_PI;
7fd59977 637 }
638 //
639 // eval the VCouture.
640 if ( (C==0) || Abs(Abs(D/C)-R) > 1.e-10) {
ef2d8af7 641 VCouture = Standard_False;
7fd59977 642 }
643 else {
ef2d8af7 644 VCouture = Standard_True;
645 UCouture = Standard_True;
646
647 if ( D/C < 0.) {
648 myV1 = - M_PI / 2.;
649 myV2 = 3 * M_PI / 2.;
650 }
651 else {
652 myV1 = -3 * M_PI / 2.;
653 myV2 = M_PI / 2.;
654 }
655
656 // si P1.Z() vaut +/- R on est sur le sommet : pas significatif.
657 gp_Pnt pp = P1.Transformed(Trsf);
658
659 if ( Abs( Abs(pp.Z()) - R) < Tol) {
660 gp_Pnt Center = Circle.Location();
661 Standard_Real U,V;
662 ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
663 myU1 = U-M_PI;
664 myU2 = U+M_PI;
665 VCouture = Standard_False;
666 }
7fd59977 667 }
ef2d8af7 668
7fd59977 669 // box+sphere >>
670 myV1 = -1.e+100; myV2 = 1.e+100;
6f7c5420 671
672 //+This fragment was the reason of bug # 26008.
673 //+It has been deleted on April, 03 2015.
674 //Standard_Real UU1 = myU1, UU2 = myU2;
675 //if((Abs(UU1) <= (2.*M_PI) && Abs(UU2) <= (2.*M_PI)) && NbSolutions == 1 && reCalc) {
676 // gp_Pnt Center = Circle.Location();
677 // Standard_Real U,V;
678 // ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
679 // myU1 = U-M_PI;
680 // myU1 = Min(UU1,myU1);
681 // myU2 = myU1 + 2.*M_PI;
682 //}
7fd59977 683 // box+sphere <<
684
685 }//if ( myCurve->GetType() == GeomAbs_Circle)
686
687 else {
688 Standard_Real U1, V1, U , V;
689 ElSLib::Parameters( SP, P1, U1, V1);
0a40a30d 690 Standard_Real R = SP.Radius();
691 Standard_Real Delta = 0., Step;
c6541a0c 692 Standard_Real eps = M_PI, dmax = 0., d = 0.;
0a40a30d 693 Step = Function_ComputeStep(myCurve, R);
7fd59977 694 myU1 = U1; myU2 = U1;
695 Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step;
696 for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
ef2d8af7 697 P = myCurve->Value(par);
698 ElSLib::Parameters( SP, P, U, V);
699 U += Delta;
700 d = U - U1;
701 if(d > eps) {
702 U -= Delta;
703 Delta -= 2*M_PI;
704 U += Delta;
705 d = U - U1;
706 }
707 else if(d < -eps) {
708 U -= Delta;
709 Delta += 2*M_PI;
710 U += Delta;
711 d = U - U1;
712 }
713 dmax = Max(dmax, Abs(d));
714 if(U < myU1) {myU1 = U; pmin = par;}
715 if(U > myU2) {myU2 = U; pmax = par;}
716 U1 = U;
7fd59977 717 }
ef2d8af7 718
7fd59977 719 if(!(Abs(pmin - W1) <= Precision::PConfusion() ||
ef2d8af7 720 Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
7fd59977 721 if(!(Abs(pmax - W1) <= Precision::PConfusion() ||
ef2d8af7 722 Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
723
c6541a0c 724 if((myU1 >=0. && myU1 <= 2*M_PI) &&
ef2d8af7 725 (myU2 >=0. && myU2 <= 2*M_PI) ) {
726 myU1 = 0.;
727 myU2 = 2.*M_PI;
728 UCouture = Standard_False;
7fd59977 729 }
730 else {
ef2d8af7 731 U = ( myU1 + myU2 ) /2.;
732 myU1 = U - M_PI;
733 myU2 = U + M_PI;
734 UCouture = Standard_True;
7fd59977 735 }
ef2d8af7 736
7fd59977 737 VCouture = Standard_False;
738 }
739 }
ef2d8af7 740 break;
741 //
7fd59977 742 case GeomAbs_Torus:{
743 gp_Torus TR = mySurface->Torus();
0a40a30d 744 Standard_Real U1, V1, U , V, dU, dV;
7fd59977 745 ElSLib::Parameters( TR, P1, U1, V1);
0a40a30d 746 Standard_Real R = TR.MinorRadius();
747 Standard_Real DeltaU = 0., DeltaV = 0., Step;
748 Standard_Real eps = M_PI, dmaxU = 0., dmaxV = 0.;
749 Step = Function_ComputeStep(myCurve, R);
7fd59977 750 myU1 = U1; myU2 = U1;
751 myV1 = V1; myV2 = V1;
752 Standard_Real pminU = W1, pmaxU = W1, pminV = W1, pmaxV = W1,
ef2d8af7 753 plim = W2+.1*Step;
7fd59977 754 for(Standard_Real par = W1 + Step; par <= plim; par += Step) {
755 P = myCurve->Value(par);
756 ElSLib::Parameters( TR, P, U, V);
757 U += DeltaU;
758 V += DeltaV;
759 dU = U - U1;
760 dV = V - V1;
761 if(dU > eps) {
ef2d8af7 762 U -= DeltaU;
763 DeltaU -= 2*M_PI;
764 U += DeltaU;
765 dU = U - U1;
7fd59977 766 }
767 else if(dU < -eps) {
ef2d8af7 768 U -= DeltaU;
769 DeltaU += 2*M_PI;
770 U += DeltaU;
771 dU = U - U1;
7fd59977 772 }
773 if(dV > eps) {
ef2d8af7 774 V -= DeltaV;
775 DeltaV -= 2*M_PI;
776 V += DeltaV;
777 dV = V - V1;
7fd59977 778 }
779 else if(dV < -eps) {
ef2d8af7 780 V -= DeltaV;
781 DeltaV += 2*M_PI;
782 V += DeltaV;
783 dV = V - V1;
7fd59977 784 }
785 dmaxU = Max(dmaxU, Abs(dU));
786 dmaxV = Max(dmaxV, Abs(dV));
787 if(U < myU1) {myU1 = U; pminU = par;}
788 if(U > myU2) {myU2 = U; pmaxU = par;}
789 if(V < myV1) {myV1 = V; pminV = par;}
790 if(V > myV2) {myV2 = V; pmaxV = par;}
791 U1 = U;
792 V1 = V;
793 }
ef2d8af7 794
7fd59977 795 if(!(Abs(pminU - W1) <= Precision::PConfusion() ||
ef2d8af7 796 Abs(pminU - W2) <= Precision::PConfusion()) ) myU1 -= dmaxU*.5;
7fd59977 797 if(!(Abs(pmaxU - W1) <= Precision::PConfusion() ||
ef2d8af7 798 Abs(pmaxU - W2) <= Precision::PConfusion()) ) myU2 += dmaxU*.5;
7fd59977 799 if(!(Abs(pminV - W1) <= Precision::PConfusion() ||
ef2d8af7 800 Abs(pminV - W2) <= Precision::PConfusion()) ) myV1 -= dmaxV*.5;
7fd59977 801 if(!(Abs(pmaxV - W1) <= Precision::PConfusion() ||
ef2d8af7 802 Abs(pmaxV - W2) <= Precision::PConfusion()) ) myV2 += dmaxV*.5;
803
c6541a0c 804 if((myU1 >=0. && myU1 <= 2*M_PI) &&
ef2d8af7 805 (myU2 >=0. && myU2 <= 2*M_PI) ) {
806 myU1 = 0.;
807 myU2 = 2.*M_PI;
808 UCouture = Standard_False;
7fd59977 809 }
810 else {
811 U = ( myU1 + myU2 ) /2.;
c6541a0c
D
812 myU1 = U - M_PI;
813 myU2 = U + M_PI;
7fd59977 814 UCouture = Standard_True;
815 }
c6541a0c 816 if((myV1 >=0. && myV1 <= 2*M_PI) &&
ef2d8af7 817 (myV2 >=0. && myV2 <= 2*M_PI) ) {
818 VCouture = Standard_False;
7fd59977 819 }
820 else {
821 V = ( myV1 + myV2 ) /2.;
c6541a0c
D
822 myV1 = V - M_PI;
823 myV2 = V + M_PI;
ef2d8af7 824 VCouture = Standard_True;
7fd59977 825 }
ef2d8af7 826
7fd59977 827 }
ef2d8af7 828 break;
829
7fd59977 830 default:
831 {
832 UCouture = Standard_False;
833 VCouture = Standard_False;
834 }
835 break;
836 }
837}
838//
7fd59977 839//
840//=======================================================================
841//classn : ProjLib_Function
842//purpose :
843//=======================================================================
368cdde6 844class ProjLib_Function : public AppCont_Function
7fd59977 845{
846 Handle(Adaptor3d_HCurve) myCurve;
847 Handle(Adaptor3d_HSurface) mySurface;
368cdde6 848 Standard_Boolean myIsPeriodic[2];
849 Standard_Real myPeriod[2];
7fd59977 850 public :
851
852 Standard_Real myU1,myU2,myV1,myV2;
853 Standard_Boolean UCouture,VCouture;
368cdde6 854
7fd59977 855 ProjLib_Function(const Handle(Adaptor3d_HCurve)& C,
368cdde6 856 const Handle(Adaptor3d_HSurface)& S)
857: myCurve(C),
858 mySurface(S),
7fd59977 859 myU1(0.0),
860 myU2(0.0),
861 myV1(0.0),
862 myV2(0.0),
863 UCouture(Standard_False),
864 VCouture(Standard_False)
368cdde6 865 {
866 myNbPnt = 0;
867 myNbPnt2d = 1;
868 Function_SetUVBounds(myU1,myU2,myV1,myV2,UCouture,VCouture,myCurve,mySurface);
869 myIsPeriodic[0] = mySurface->IsUPeriodic();
870 myIsPeriodic[1] = mySurface->IsVPeriodic();
871
872 if (myIsPeriodic[0])
873 myPeriod[0] = mySurface->UPeriod();
874 else
875 myPeriod[0] = 0.0;
876
877 if (myIsPeriodic[1])
878 myPeriod[1] = mySurface->VPeriod();
879 else
880 myPeriod[1] = 0.0;
881 }
882
883 void PeriodInformation(const Standard_Integer theDimIdx,
884 Standard_Boolean& IsPeriodic,
885 Standard_Real& thePeriod) const
886 {
887 IsPeriodic = myIsPeriodic[theDimIdx - 1];
888 thePeriod = myPeriod[theDimIdx - 1];
889 }
890
7fd59977 891 Standard_Real FirstParameter() const
368cdde6 892 {
893 return (myCurve->FirstParameter());
894 }
895
7fd59977 896 Standard_Real LastParameter() const
368cdde6 897 {
898 return (myCurve->LastParameter());
899 }
900
901 Standard_Boolean Value(const Standard_Real theT,
902 NCollection_Array1<gp_Pnt2d>& thePnt2d,
903 NCollection_Array1<gp_Pnt>& /*thePnt*/) const
904 {
905 thePnt2d(1) = Function_Value(theT, myCurve, mySurface, myU1, myU2, myV1, myV2, UCouture, VCouture);
906 return Standard_True;
907 }
908
909 gp_Pnt2d Value(const Standard_Real theT) const
910 {
911 return Function_Value(theT, myCurve, mySurface, myU1, myU2, myV1, myV2, UCouture, VCouture);
912 }
913
914 Standard_Boolean D1(const Standard_Real theT,
915 NCollection_Array1<gp_Vec2d>& theVec2d,
916 NCollection_Array1<gp_Vec>& /*theVec*/) const
917 {
918 gp_Pnt2d aPnt2d;
919 gp_Vec2d aVec2d;
920 Standard_Boolean isOk = Function_D1(theT, aPnt2d,aVec2d, myCurve, mySurface, myU1, myU2, myV1, myV2, UCouture, VCouture);
921 theVec2d(1) = aVec2d;
922 return isOk;
923 }
7fd59977 924};
925
3065019c 926//=======================================================================
927//function : ComputeTolU
928//purpose :
929//=======================================================================
930
931static Standard_Real ComputeTolU(const Handle(Adaptor3d_HSurface)& theSurf,
932 const Standard_Real theTolerance)
933{
934 Standard_Real aTolU = theSurf->UResolution(theTolerance);
935 if (theSurf->IsUPeriodic())
936 {
937 aTolU = Min(aTolU, 0.01*theSurf->UPeriod());
938 }
939
940 return aTolU;
941}
942
943//=======================================================================
944//function : ComputeTolV
945//purpose :
946//=======================================================================
947
948static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf,
949 const Standard_Real theTolerance)
950{
951 Standard_Real aTolV = theSurf->VResolution(theTolerance);
952 if (theSurf->IsVPeriodic())
953 {
954 aTolV = Min(aTolV, 0.01*theSurf->VPeriod());
955 }
956
957 return aTolV;
958}
959
7fd59977 960//=======================================================================
961//function : ProjLib_ComputeApprox
962//purpose :
963//=======================================================================
964
965ProjLib_ComputeApprox::ProjLib_ComputeApprox
966 (const Handle(Adaptor3d_HCurve) & C,
967 const Handle(Adaptor3d_HSurface) & S,
968 const Standard_Real Tol )
969{
970 // if the surface is a plane and the curve a BSpline or a BezierCurve,
971 // don`t make an Approx but only the projection of the poles.
972
973 myTolerance = Max(Precision::PApproximation(),Tol);
974 Standard_Integer NbKnots, NbPoles ;
975 GeomAbs_CurveType CType = C->GetType();
976 GeomAbs_SurfaceType SType = S->GetType();
977
978 Standard_Boolean SurfIsAnal = (SType != GeomAbs_BSplineSurface) &&
979 (SType != GeomAbs_BezierSurface) &&
980 (SType != GeomAbs_OtherSurface) ;
981
982 Standard_Boolean CurvIsAnal = (CType != GeomAbs_BSplineCurve) &&
983 (CType != GeomAbs_BezierCurve) &&
1aec3320 984 (CType != GeomAbs_OffsetCurve) &&
7fd59977 985 (CType != GeomAbs_OtherCurve) ;
986
987 Standard_Boolean simplecase = SurfIsAnal && CurvIsAnal;
988
989 if (CType == GeomAbs_BSplineCurve &&
990 SType == GeomAbs_Plane ) {
991
992 // get the poles and eventually the weights
993 Handle(Geom_BSplineCurve) BS = C->BSpline();
994 NbPoles = BS->NbPoles();
995 TColgp_Array1OfPnt P3d( 1, NbPoles);
996 TColgp_Array1OfPnt2d Poles( 1, NbPoles);
997 TColStd_Array1OfReal Weights( 1, NbPoles);
998 if ( BS->IsRational()) BS->Weights(Weights);
999 BS->Poles( P3d);
1000 gp_Pln Plane = S->Plane();
1001 Standard_Real U,V;
1002 for ( Standard_Integer i = 1; i <= NbPoles; i++) {
1003 ElSLib::Parameters( Plane, P3d(i), U, V);
1004 Poles.SetValue(i,gp_Pnt2d(U,V));
1005 }
1006 NbKnots = BS->NbKnots();
1007 TColStd_Array1OfReal Knots(1,NbKnots);
1008 TColStd_Array1OfInteger Mults(1,NbKnots);
1009 BS->Knots(Knots) ;
1010 BS->Multiplicities(Mults) ;
1011 // get the knots and mults if BSplineCurve
1012 if ( BS->IsRational()) {
1013 myBSpline = new Geom2d_BSplineCurve(Poles,
1014 Weights,
1015 Knots,
1016 Mults,
1017 BS->Degree(),
1018 BS->IsPeriodic());
1019 }
1020 else {
1021 myBSpline = new Geom2d_BSplineCurve(Poles,
1022 Knots,
1023 Mults,
1024 BS->Degree(),
1025 BS->IsPeriodic());
1026 }
1027 }
1028 else if (CType == GeomAbs_BezierCurve &&
1029 SType == GeomAbs_Plane ) {
1030
1031 // get the poles and eventually the weights
1032 Handle(Geom_BezierCurve) BezierCurvePtr = C->Bezier() ;
1033 NbPoles = BezierCurvePtr->NbPoles();
1034 TColgp_Array1OfPnt P3d( 1, NbPoles);
1035 TColgp_Array1OfPnt2d Poles( 1, NbPoles);
1036 TColStd_Array1OfReal Weights( 1, NbPoles);
1037 if ( BezierCurvePtr->IsRational()) {
1038 BezierCurvePtr->Weights(Weights);
1039 }
1040 BezierCurvePtr->Poles( P3d);
1041
1042 // project the 3D-Poles on the plane
1043
1044 gp_Pln Plane = S->Plane();
1045 Standard_Real U,V;
1046 for ( Standard_Integer i = 1; i <= NbPoles; i++) {
1047 ElSLib::Parameters( Plane, P3d(i), U, V);
1048 Poles.SetValue(i,gp_Pnt2d(U,V));
1049 }
1050 if ( BezierCurvePtr->IsRational()) {
1051 myBezier = new Geom2d_BezierCurve(Poles, Weights);
1052 }
1053 else {
1054 myBezier = new Geom2d_BezierCurve(Poles);
1055 }
1056 }
1057 else {
1058 ProjLib_Function F( C, S);
1059
0797d9d3 1060#ifdef OCCT_DEBUG
6f7c5420 1061 //if ( AffichValue) {
1062 // Standard_Integer Nb = 20;
1063 // Standard_Real U1, U2, dU, U;
1064 // U1 = F.FirstParameter();
1065 // U2 = F.LastParameter();
1066 // dU = ( U2 - U1) / Nb;
1067 // TColStd_Array1OfInteger Mults(1,Nb+1);
1068 // TColStd_Array1OfReal Knots(1,Nb+1);
1069 // TColgp_Array1OfPnt2d Poles(1,Nb+1);
1070 // for ( Standard_Integer i = 1; i <= Nb+1; i++) {
1071 // U = U1 + (i-1)*dU;
1072 // Poles(i) = F.Value(U);
1073 // cout << "i = " << i << ": U = " << U <<
1074 // ", p(" << Poles(i).X() << ", " << Poles(i).Y() << ");" << endl;
1075 // Knots(i) = i;
1076 // Mults(i) = 1;
1077 // }
1078 // Mults(1) = 2;
1079 // Mults(Nb+1) = 2;
1080
1081 //2D-curve for showing in DRAW
1082 // Handle(Geom2d_Curve) aCC = new Geom2d_BSplineCurve(Poles,Knots,Mults,1);
1083 // AffichValue = Standard_False;
1084 //}
7fd59977 1085#endif
1086
1087//-----------
1088 Standard_Integer Deg1, Deg2;
1089 if(simplecase) {
1090 Deg1 = 8;
1091 Deg2 = 10;
1092 }
1093 else {
1094 Deg1 = 8;
1095 Deg2 = 12;
1096 }
1097//-------------
3065019c 1098 const Standard_Real aTolU = ComputeTolU(S, myTolerance);
1099 const Standard_Real aTolV = ComputeTolV(S, myTolerance);
1100 const Standard_Real aTol2d = Max(Sqrt(aTolU*aTolU + aTolV*aTolV), Precision::PConfusion());
1101
1102 Approx_FitAndDivide2d Fit(F, Deg1, Deg2, myTolerance, aTol2d, Standard_True);
1103
1104 Standard_Real aNewTol2d = 0;
7fd59977 1105 if(Fit.IsAllApproximated()) {
1106 Standard_Integer i;
1107 Standard_Integer NbCurves = Fit.NbMultiCurves();
1108
1109 // on essaie de rendre la courbe au moins C1
1110 Convert_CompBezierCurves2dToBSplineCurve2d Conv;
1111
7fd59977 1112 Standard_Real Tol3d,Tol2d;
1113 for (i = 1; i <= NbCurves; i++) {
ef2d8af7 1114 Fit.Error(i,Tol3d, Tol2d);
3065019c 1115 aNewTol2d = Max(aNewTol2d, Tol2d);
ef2d8af7 1116 AppParCurves_MultiCurve MC = Fit.Value( i); //Charge la Ieme Curve
1117 TColgp_Array1OfPnt2d Poles2d( 1, MC.Degree() + 1);//Recupere les poles
1118 MC.Curve(1, Poles2d);
1119
1120 Conv.AddCurve(Poles2d);
7fd59977 1121 }
368cdde6 1122
1123 //mise a jour des fields de ProjLib_Approx
7fd59977 1124 Conv.Perform();
7fd59977 1125 NbPoles = Conv.NbPoles();
1126 NbKnots = Conv.NbKnots();
1127
7fd59977 1128 if(NbPoles <= 0 || NbPoles > 100000)
368cdde6 1129 return;
7fd59977 1130 if(NbKnots <= 0 || NbKnots > 100000)
368cdde6 1131 return;
7fd59977 1132
1133 TColgp_Array1OfPnt2d NewPoles(1,NbPoles);
1134 TColStd_Array1OfReal NewKnots(1,NbKnots);
1135 TColStd_Array1OfInteger NewMults(1,NbKnots);
368cdde6 1136
7fd59977 1137 Conv.KnotsAndMults(NewKnots,NewMults);
1138 Conv.Poles(NewPoles);
368cdde6 1139
7fd59977 1140 BSplCLib::Reparametrize(C->FirstParameter(),
368cdde6 1141 C->LastParameter(),
1142 NewKnots);
1143
1144 /*cout << endl;
1145 for (int i = 1; i <= NbPoles; i++)
1146 {
1147 cout << NewPoles.Value(i).X() << " " << NewPoles.Value(i).Y() << endl;
1148 }
1149 cout << endl; */
1150
7fd59977 1151 // il faut recadrer les poles de debut et de fin:
1152 // ( Car pour les problemes de couture, on a du ouvrir l`intervalle
1153 // de definition de la courbe.)
1154 // On choisit de calculer ces poles par prolongement de la courbe
1155 // approximee.
7fd59977 1156 myBSpline = new Geom2d_BSplineCurve (NewPoles,
368cdde6 1157 NewKnots,
1158 NewMults,
1159 Conv.Degree());
7fd59977 1160 }
1161 else {
1162 Standard_Integer NbCurves = Fit.NbMultiCurves();
1163 if(NbCurves != 0) {
ef2d8af7 1164 Standard_Real Tol3d,Tol2d;
1165 Fit.Error(NbCurves,Tol3d, Tol2d);
3065019c 1166 aNewTol2d = Tol2d;
7fd59977 1167 }
1168 }
1169
3065019c 1170 // restore tolerance 3d from 2d
1171
1172 //Here we consider that
1173 // aTolU(new)/aTolV(new) = aTolU(old)/aTolV(old)
1174 //(it is assumption indeed).
1175 //Then,
1176 // Tol3D(new)/Tol3D(old) = Tol2D(new)/Tol2D(old).
1177 myTolerance *= (aNewTol2d / aTol2d);
1178
7fd59977 1179 //Return curve home
1180 Standard_Real UFirst = F.FirstParameter();
1181 gp_Pnt P3d = C->Value( UFirst );
1d47d8d0 1182 Standard_Real u = 0., v = 0.;
7fd59977 1183 switch (SType)
ef2d8af7 1184 {
1185 case GeomAbs_Plane:
1186 {
1187 gp_Pln Plane = S->Plane();
1188 ElSLib::Parameters( Plane, P3d, u, v );
1189 break;
1190 }
1191 case GeomAbs_Cylinder:
1192 {
1193 gp_Cylinder Cylinder = S->Cylinder();
1194 ElSLib::Parameters( Cylinder, P3d, u, v );
1195 break;
1196 }
1197 case GeomAbs_Cone:
7fd59977 1198 {
ef2d8af7 1199 gp_Cone Cone = S->Cone();
1200 ElSLib::Parameters( Cone, P3d, u, v );
1201 break;
7fd59977 1202 }
ef2d8af7 1203 case GeomAbs_Sphere:
1204 {
1205 gp_Sphere Sphere = S->Sphere();
1206 ElSLib::Parameters( Sphere, P3d, u, v );
1207 break;
1208 }
1209 case GeomAbs_Torus:
1210 {
1211 gp_Torus Torus = S->Torus();
1212 ElSLib::Parameters( Torus, P3d, u, v );
1213 break;
1214 }
1215 default:
9775fa61 1216 throw Standard_NoSuchObject("ProjLib_ComputeApprox::Value");
ef2d8af7 1217 }
7fd59977 1218 Standard_Boolean ToMirror = Standard_False;
1219 Standard_Real du = 0., dv = 0.;
1220 Standard_Integer number;
1221 if (F.VCouture)
ef2d8af7 1222 {
1223 if (SType == GeomAbs_Sphere && Abs(u-F.myU1) > M_PI)
7fd59977 1224 {
ef2d8af7 1225 ToMirror = Standard_True;
1226 dv = -M_PI;
1227 v = M_PI - v;
7fd59977 1228 }
ef2d8af7 1229 Standard_Real newV = ElCLib::InPeriod( v, F.myV1, F.myV2 );
1230 number = (Standard_Integer) (Floor((newV-v)/(F.myV2-F.myV1)));
1231 dv -= number*(F.myV2-F.myV1);
1232 }
1233 if (F.UCouture || (F.VCouture && SType == GeomAbs_Sphere))
1234 {
6aa39ac3 1235 Standard_Real aNbPer;
1236 gp_Pnt2d P2d = F.Value(UFirst);
1237 du = u - P2d.X();
1238 du = (du < 0) ? (du - Precision::PConfusion()) :
1239 (du + Precision::PConfusion());
1240 modf(du/M_PI, &aNbPer);
1241 number = (Standard_Integer)aNbPer;
1242 du = number*M_PI;
ef2d8af7 1243 }
7fd59977 1244
1245 if (!myBSpline.IsNull())
ef2d8af7 1246 {
1247 if (du != 0. || dv != 0.)
1248 myBSpline->Translate( gp_Vec2d(du,dv) );
1249 if (ToMirror)
7fd59977 1250 {
ef2d8af7 1251 gp_Ax2d Axe( gp_Pnt2d(0.,0.), gp_Dir2d(1.,0.) );
1252 myBSpline->Mirror( Axe );
7fd59977 1253 }
ef2d8af7 1254 }
7fd59977 1255 }
1256}
1257
1258//=======================================================================
1259//function : BSpline
1260//purpose :
1261//=======================================================================
1262
1263Handle(Geom2d_BSplineCurve) ProjLib_ComputeApprox::BSpline() const
1264
1265{
1266 return myBSpline ;
1267}
1268
1269//=======================================================================
1270//function : Bezier
1271//purpose :
1272//=======================================================================
1273
1274Handle(Geom2d_BezierCurve) ProjLib_ComputeApprox::Bezier() const
1275
1276{
1277 return myBezier ;
1278}
1279
1280
1281//=======================================================================
1282//function : Tolerance
1283//purpose :
1284//=======================================================================
1285
1286Standard_Real ProjLib_ComputeApprox::Tolerance() const
1287{
1288 return myTolerance;
1289}
1290
1291