1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 //-----------------------------
16 //-- IntWalk_PWalking_1.gxx
19 #include <Precision.hxx>
20 #include <math_FunctionSetRoot.hxx>
22 #include <Geom_Surface.hxx>
26 //==================================================================================
27 // function : IntWalk_PWalking::IntWalk_PWalking
29 // estimate of max step : To avoid abrupt changes
30 // during change of isos
31 //==================================================================================
32 void ComputePasInit(Standard_Real *pasuv,
33 Standard_Real Um1,Standard_Real UM1,
34 Standard_Real Vm1,Standard_Real VM1,
35 Standard_Real Um2,Standard_Real UM2,
36 Standard_Real Vm2,Standard_Real VM2,
37 Standard_Real _Um1,Standard_Real _UM1,
38 Standard_Real _Vm1,Standard_Real _VM1,
39 Standard_Real _Um2,Standard_Real _UM2,
40 Standard_Real _Vm2,Standard_Real _VM2,
43 const Standard_Real Increment)
45 Standard_Real du1=Abs(UM1-Um1);
46 Standard_Real dv1=Abs(VM1-Vm1);
47 Standard_Real du2=Abs(UM2-Um2);
48 Standard_Real dv2=Abs(VM2-Vm2);
50 Standard_Real _du1=Abs(_UM1-_Um1);
51 Standard_Real _dv1=Abs(_VM1-_Vm1);
52 Standard_Real _du2=Abs(_UM2-_Um2);
53 Standard_Real _dv2=Abs(_VM2-_Vm2);
55 //-- limit the reduction of uv box estimate to 0.01 natural box
56 //-- du1 : On box of Inter
57 //-- _du1 : On parametric space
58 if(_du1<1e50 && du1<0.01*_du1) du1=0.01*_du1;
59 if(_dv1<1e50 && dv1<0.01*_dv1) dv1=0.01*_dv1;
60 if(_du2<1e50 && du2<0.01*_du2) du2=0.01*_du2;
61 if(_dv2<1e50 && dv2<0.01*_dv2) dv2=0.01*_dv2;
63 pasuv[0]=Increment*du1;
64 pasuv[1]=Increment*dv1;
65 pasuv[2]=Increment*du2;
66 pasuv[3]=Increment*dv2;
69 //=======================================================================
70 //function : IsParallel
71 //purpose : Checks if theLine is parallel of some boundary of given
72 // surface (it is determined by theCheckSurf1 flag).
73 // Parallelism assumes small oscillations (swing is less or
74 // equal than theToler).
75 // Small lines (if first and last parameters in the Surface
76 // are almost equal) are classified as parallel (as same as
77 // any point can be considered as parallel of any line).
78 //=======================================================================
79 static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
80 const Standard_Boolean theCheckSurf1,
81 const Standard_Real theToler,
82 Standard_Boolean& theIsUparallel,
83 Standard_Boolean& theIsVparallel)
85 const Standard_Integer aNbPointsMAX = 23;
87 theIsUparallel = theIsVparallel = Standard_True;
89 Standard_Integer aNbPoints = theLine->NbPoints();
90 if(aNbPoints > aNbPointsMAX)
92 aNbPoints = aNbPointsMAX;
94 else if(aNbPoints < 3)
96 //Here we cannot estimate parallelism.
97 //Do all same as for small lines
101 Standard_Real aStep = IntToReal(theLine->NbPoints()) / aNbPoints;
102 Standard_Real aNPoint = 1.0;
104 Standard_Real aUmin = RealLast(), aUmax = RealFirst(), aVmin = RealLast(), aVmax = RealFirst();
105 for(Standard_Integer aNum = 1; aNum <= aNbPoints; aNum++, aNPoint += aStep)
107 if(aNPoint > aNbPoints)
114 theLine->Value(RealToInt(aNPoint)).ParametersOnS1(u, v);
116 theLine->Value(RealToInt(aNPoint)).ParametersOnS2(u, v);
131 theIsVparallel = ((aUmax - aUmin) < theToler);
132 theIsUparallel = ((aVmax - aVmin) < theToler);
135 //=======================================================================
136 //function : Checking
137 //purpose : Check, if given point is in surface's boundaries.
138 // If "yes" then theFactTol = 0.0, else theFactTol is
139 // equal maximal deviation.
140 //=======================================================================
141 static Standard_Boolean Checking( const Handle(Adaptor3d_HSurface)& theASurf1,
142 const Handle(Adaptor3d_HSurface)& theASurf2,
143 Standard_Real& theU1,
144 Standard_Real& theV1,
145 Standard_Real& theU2,
146 Standard_Real& theV2,
147 Standard_Real& theFactTol)
149 const Standard_Real aTol = Precision::PConfusion();
150 const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
151 const Standard_Real aU1bLast = theASurf1->LastUParameter();
152 const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
153 const Standard_Real aU2bLast = theASurf2->LastUParameter();
154 const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
155 const Standard_Real aV1bLast = theASurf1->LastVParameter();
156 const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
157 const Standard_Real aV2bLast = theASurf2->LastVParameter();
159 Standard_Boolean isOnOrIn = Standard_True;
162 Standard_Real aDelta = aU1bFirst - theU1;
166 theFactTol = Max(theFactTol, aDelta);
167 isOnOrIn = Standard_False;
170 aDelta = theU1 - aU1bLast;
174 theFactTol = Max(theFactTol, aDelta);
175 isOnOrIn = Standard_False;
178 aDelta = aV1bFirst - theV1;
182 theFactTol = Max(theFactTol, aDelta);
183 isOnOrIn = Standard_False;
186 aDelta = theV1 - aV1bLast;
190 theFactTol = Max(theFactTol, aDelta);
191 isOnOrIn = Standard_False;
194 aDelta = aU2bFirst - theU2;
198 theFactTol = Max(theFactTol, aDelta);
199 isOnOrIn = Standard_False;
202 aDelta = theU2 - aU2bLast;
206 theFactTol = Max(theFactTol, aDelta);
207 isOnOrIn = Standard_False;
210 aDelta = aV2bFirst - theV2;
214 theFactTol = Max(theFactTol, aDelta);
215 isOnOrIn = Standard_False;
218 aDelta = theV2 - aV2bLast;
222 theFactTol = Max(theFactTol, aDelta);
223 isOnOrIn = Standard_False;
229 //==================================================================================
230 // function : IntWalk_PWalking::IntWalk_PWalking
232 //==================================================================================
233 IntWalk_PWalking::IntWalk_PWalking(const ThePSurface& Caro1,
234 const ThePSurface& Caro2,
235 const Standard_Real TolTangency,
236 const Standard_Real Epsilon,
237 const Standard_Real Deflection,
238 const Standard_Real Increment )
242 close(Standard_False),
246 myIntersectionOn2S(Caro1,Caro2,TolTangency),
247 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND(0),
248 STATIC_PRECEDENT_INFLEXION(0)
250 Standard_Real KELARG=20.;
252 pasMax=Increment*0.2; //-- June 25 99 after problems with precision
253 Um1 = ThePSurfaceTool::FirstUParameter(Caro1);
254 Vm1 = ThePSurfaceTool::FirstVParameter(Caro1);
255 UM1 = ThePSurfaceTool::LastUParameter(Caro1);
256 VM1 = ThePSurfaceTool::LastVParameter(Caro1);
258 Um2 = ThePSurfaceTool::FirstUParameter(Caro2);
259 Vm2 = ThePSurfaceTool::FirstVParameter(Caro2);
260 UM2 = ThePSurfaceTool::LastUParameter(Caro2);
261 VM2 = ThePSurfaceTool::LastVParameter(Caro2);
263 ResoU1 = ThePSurfaceTool::UResolution(Caro1,Precision::Confusion());
264 ResoV1 = ThePSurfaceTool::VResolution(Caro1,Precision::Confusion());
266 ResoU2 = ThePSurfaceTool::UResolution(Caro2,Precision::Confusion());
267 ResoV2 = ThePSurfaceTool::VResolution(Caro2,Precision::Confusion());
269 Standard_Real NEWRESO;
270 Standard_Real MAXVAL;
271 Standard_Real MAXVAL2;
273 MAXVAL = Abs(Um1); MAXVAL2 = Abs(UM1);
274 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
275 NEWRESO = ResoU1 * MAXVAL ;
276 if(NEWRESO > ResoU1 &&NEWRESO<10) { ResoU1 = NEWRESO; }
279 MAXVAL = Abs(Um2); MAXVAL2 = Abs(UM2);
280 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
281 NEWRESO = ResoU2 * MAXVAL ;
282 if(NEWRESO > ResoU2 && NEWRESO<10) { ResoU2 = NEWRESO; }
285 MAXVAL = Abs(Vm1); MAXVAL2 = Abs(VM1);
286 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
287 NEWRESO = ResoV1 * MAXVAL ;
288 if(NEWRESO > ResoV1 && NEWRESO<10) { ResoV1 = NEWRESO; }
291 MAXVAL = Abs(Vm2); MAXVAL2 = Abs(VM2);
292 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
293 NEWRESO = ResoV2 * MAXVAL ;
294 if(NEWRESO > ResoV2 && NEWRESO<10) { ResoV2 = NEWRESO; }
296 pasuv[0]=pasMax*Abs(UM1-Um1);
297 pasuv[1]=pasMax*Abs(VM1-Vm1);
298 pasuv[2]=pasMax*Abs(UM2-Um2);
299 pasuv[3]=pasMax*Abs(VM2-Vm2);
301 if(ResoU1>0.0001*pasuv[0]) ResoU1=0.00001*pasuv[0];
302 if(ResoV1>0.0001*pasuv[1]) ResoV1=0.00001*pasuv[1];
303 if(ResoU2>0.0001*pasuv[2]) ResoU2=0.00001*pasuv[2];
304 if(ResoV2>0.0001*pasuv[3]) ResoV2=0.00001*pasuv[3];
307 if(ThePSurfaceTool::IsUPeriodic(Caro1)==Standard_False) {
308 //UM1+=KELARG*pasuv[0]; Um1-=KELARG*pasuv[0];
311 Standard_Real t = UM1-Um1;
312 if(t<ThePSurfaceTool::UPeriod(Caro1)) {
313 t=0.5*(ThePSurfaceTool::UPeriod(Caro1)-t);
314 t=(t>KELARG*pasuv[0])? KELARG*pasuv[0] : t;
319 if(ThePSurfaceTool::IsVPeriodic(Caro1)==Standard_False) {
320 //VM1+=KELARG*pasuv[1]; Vm1-=KELARG*pasuv[1];
323 Standard_Real t = VM1-Vm1;
324 if(t<ThePSurfaceTool::VPeriod(Caro1)) {
325 t=0.5*(ThePSurfaceTool::VPeriod(Caro1)-t);
326 t=(t>KELARG*pasuv[1])? KELARG*pasuv[1] : t;
331 if(ThePSurfaceTool::IsUPeriodic(Caro2)==Standard_False) {
332 //UM2+=KELARG*pasuv[2]; Um2-=KELARG*pasuv[2];
335 Standard_Real t = UM2-Um2;
336 if(t<ThePSurfaceTool::UPeriod(Caro2)) {
337 t=0.5*(ThePSurfaceTool::UPeriod(Caro2)-t);
338 t=(t>KELARG*pasuv[2])? KELARG*pasuv[2] : t;
343 if(ThePSurfaceTool::IsVPeriodic(Caro2)==Standard_False) {
344 //VM2+=KELARG*pasuv[3]; Vm2-=KELARG*pasuv[3];
347 Standard_Real t = VM2-Vm2;
348 if(t<ThePSurfaceTool::VPeriod(Caro2)) {
349 t=0.5*(ThePSurfaceTool::VPeriod(Caro2)-t);
350 t=(t>KELARG*pasuv[3])? KELARG*pasuv[3] : t;
355 //-- ComputePasInit(pasuv,Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2);
357 for (Standard_Integer i = 0; i<=3;i++) {
360 pasInit[i] = pasSav[i] = pasuv[i];
365 //==================================================================================
366 // function : IntWalk_PWalking
368 //==================================================================================
369 IntWalk_PWalking::IntWalk_PWalking(const ThePSurface& Caro1,
370 const ThePSurface& Caro2,
371 const Standard_Real TolTangency,
372 const Standard_Real Epsilon,
373 const Standard_Real Deflection,
374 const Standard_Real Increment,
375 const Standard_Real U1,
376 const Standard_Real V1,
377 const Standard_Real U2,
378 const Standard_Real V2)
382 close(Standard_False),
386 myIntersectionOn2S(Caro1,Caro2,TolTangency),
387 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND(0),
388 STATIC_PRECEDENT_INFLEXION(0)
390 Standard_Real KELARG=20.;
392 pasMax=Increment*0.2; //-- June 25 99 after problems with precision
394 Um1 = ThePSurfaceTool::FirstUParameter(Caro1);
395 Vm1 = ThePSurfaceTool::FirstVParameter(Caro1);
396 UM1 = ThePSurfaceTool::LastUParameter(Caro1);
397 VM1 = ThePSurfaceTool::LastVParameter(Caro1);
399 Um2 = ThePSurfaceTool::FirstUParameter(Caro2);
400 Vm2 = ThePSurfaceTool::FirstVParameter(Caro2);
401 UM2 = ThePSurfaceTool::LastUParameter(Caro2);
402 VM2 = ThePSurfaceTool::LastVParameter(Caro2);
404 ResoU1 = ThePSurfaceTool::UResolution(Caro1,Precision::Confusion());
405 ResoV1 = ThePSurfaceTool::VResolution(Caro1,Precision::Confusion());
407 ResoU2 = ThePSurfaceTool::UResolution(Caro2,Precision::Confusion());
408 ResoV2 = ThePSurfaceTool::VResolution(Caro2,Precision::Confusion());
410 Standard_Real NEWRESO, MAXVAL, MAXVAL2;
414 if(MAXVAL2 > MAXVAL) {
417 NEWRESO = ResoU1 * MAXVAL ;
418 if(NEWRESO > ResoU1) {
424 if(MAXVAL2 > MAXVAL){
427 NEWRESO = ResoU2 * MAXVAL ;
428 if(NEWRESO > ResoU2) {
434 if(MAXVAL2 > MAXVAL) {
437 NEWRESO = ResoV1 * MAXVAL ;
438 if(NEWRESO > ResoV1) {
444 if(MAXVAL2 > MAXVAL){
447 NEWRESO = ResoV2 * MAXVAL ;
448 if(NEWRESO > ResoV2) {
452 pasuv[0]=pasMax*Abs(UM1-Um1);
453 pasuv[1]=pasMax*Abs(VM1-Vm1);
454 pasuv[2]=pasMax*Abs(UM2-Um2);
455 pasuv[3]=pasMax*Abs(VM2-Vm2);
457 if(ThePSurfaceTool::IsUPeriodic(Caro1)==Standard_False) {
458 UM1+=KELARG*pasuv[0];
459 Um1-=KELARG*pasuv[0];
462 Standard_Real t = UM1-Um1;
463 if(t<ThePSurfaceTool::UPeriod(Caro1)) {
464 t=0.5*(ThePSurfaceTool::UPeriod(Caro1)-t);
465 t=(t>KELARG*pasuv[0])? KELARG*pasuv[0] : t;
471 if(ThePSurfaceTool::IsVPeriodic(Caro1)==Standard_False) {
472 VM1+=KELARG*pasuv[1];
473 Vm1-=KELARG*pasuv[1];
476 Standard_Real t = VM1-Vm1;
477 if(t<ThePSurfaceTool::VPeriod(Caro1)) {
478 t=0.5*(ThePSurfaceTool::VPeriod(Caro1)-t);
479 t=(t>KELARG*pasuv[1])? KELARG*pasuv[1] : t;
484 if(ThePSurfaceTool::IsUPeriodic(Caro2)==Standard_False) {
485 UM2+=KELARG*pasuv[2];
486 Um2-=KELARG*pasuv[2];
489 Standard_Real t = UM2-Um2;
490 if(t<ThePSurfaceTool::UPeriod(Caro2)) {
491 t=0.5*(ThePSurfaceTool::UPeriod(Caro2)-t);
492 t=(t>KELARG*pasuv[2])? KELARG*pasuv[2] : t;
498 if(ThePSurfaceTool::IsVPeriodic(Caro2)==Standard_False) {
499 VM2+=KELARG*pasuv[3];
500 Vm2-=KELARG*pasuv[3];
503 Standard_Real t = VM2-Vm2;
504 if(t<ThePSurfaceTool::VPeriod(Caro2)) {
505 t=0.5*(ThePSurfaceTool::VPeriod(Caro2)-t);
506 t=(t>KELARG*pasuv[3])? KELARG*pasuv[3] : t;
511 //-- ComputePasInit(pasuv,Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2);
513 for (Standard_Integer i = 0; i<=3;i++) {
514 pasInit[i] = pasSav[i] = pasuv[i];
517 if(ResoU1>0.0001*pasuv[0]) ResoU1=0.00001*pasuv[0];
518 if(ResoV1>0.0001*pasuv[1]) ResoV1=0.00001*pasuv[1];
519 if(ResoU2>0.0001*pasuv[2]) ResoU2=0.00001*pasuv[2];
520 if(ResoV2>0.0001*pasuv[3]) ResoV2=0.00001*pasuv[3];
522 TColStd_Array1OfReal Par(1,4);
530 //==================================================================================
531 // function : PerformFirstPoint
533 //==================================================================================
534 Standard_Boolean IntWalk_PWalking::PerformFirstPoint (const TColStd_Array1OfReal& ParDep,
535 IntSurf_PntOn2S& FirstPoint)
538 close = Standard_False;
541 TColStd_Array1OfReal Param(1,4);
543 for (i=1; i<=4; ++i) {
544 Param(i) = ParDep(i);
546 //-- calculate the first solution point
547 math_FunctionSetRoot Rsnld(myIntersectionOn2S.Function());
549 myIntersectionOn2S.Perform(Param,Rsnld);
550 if (!myIntersectionOn2S.IsDone()) {
551 return Standard_False;
554 if (myIntersectionOn2S.IsEmpty()) {
555 return Standard_False;
558 FirstPoint = myIntersectionOn2S.Point();
559 return Standard_True;
561 //==================================================================================
562 // function : Perform
564 //==================================================================================
565 void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep)
567 Perform(ParDep,Um1,Vm1,Um2,Vm2,UM1,VM1,UM2,VM2);
569 //==================================================================================
570 // function : Perform
572 //==================================================================================
573 void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
574 const Standard_Real u1min,
575 const Standard_Real v1min,
576 const Standard_Real u2min,
577 const Standard_Real v2min,
578 const Standard_Real u1max,
579 const Standard_Real v1max,
580 const Standard_Real u2max,
581 const Standard_Real v2max)
583 const Standard_Real aSQDistMax = 1.0e-14;
586 Standard_Integer NbPasOKConseq=0;
587 Standard_Real pasMaxSV[4], aTmp;
588 TColStd_Array1OfReal Param(1,4);
589 IntImp_ConstIsoparametric ChoixIso;
592 done = Standard_False;
595 const ThePSurface& Caro1 =myIntersectionOn2S.Function().AuxillarSurface1();
596 const ThePSurface& Caro2 =myIntersectionOn2S.Function().AuxillarSurface2();
598 const Standard_Real UFirst1 = ThePSurfaceTool::FirstUParameter(Caro1);
599 const Standard_Real VFirst1 = ThePSurfaceTool::FirstVParameter(Caro1);
600 const Standard_Real ULast1 = ThePSurfaceTool::LastUParameter (Caro1);
601 const Standard_Real VLast1 = ThePSurfaceTool::LastVParameter (Caro1);
603 const Standard_Real UFirst2 = ThePSurfaceTool::FirstUParameter(Caro2);
604 const Standard_Real VFirst2 = ThePSurfaceTool::FirstVParameter(Caro2);
605 const Standard_Real ULast2 = ThePSurfaceTool::LastUParameter (Caro2);
606 const Standard_Real VLast2 = ThePSurfaceTool::LastVParameter (Caro2);
608 ComputePasInit(pasuv,u1min,u1max,v1min,v1max,u2min,u2max,v2min,v2max,
609 Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2,pasMax+pasMax);
611 if(pasuv[0]<100.0*ResoU1) {
612 pasuv[0]=100.0*ResoU1;
614 if(pasuv[1]<100.0*ResoV1) {
615 pasuv[1]=100.0*ResoV1;
617 if(pasuv[2]<100.0*ResoU2) {
618 pasuv[2]=100.0*ResoU2;
620 if(pasuv[3]<100.0*ResoV2) {
621 pasuv[3]=100.0*ResoV2;
624 for (Standard_Integer i=0; i<4; ++i)
631 pasInit[i] = pasSav[i] = pasuv[i];
634 line = new IntSurf_LineOn2S ();
636 for (Standard_Integer i=1; i<=4; ++i)
641 //-- reproduce steps uv connected to surfaces Caro1 and Caro2
642 //-- pasuv[] and pasSav[] are modified during the marching
643 for(Standard_Integer i = 0; i < 4; ++i)
645 pasMaxSV[i] = pasSav[i] = pasuv[i] = pasInit[i];
648 //-- calculate the first solution point
649 math_FunctionSetRoot Rsnld(myIntersectionOn2S.Function());
651 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld);
652 if (!myIntersectionOn2S.IsDone())
658 if (myIntersectionOn2S.IsEmpty())
663 if(myIntersectionOn2S.IsTangent())
668 Standard_Boolean Arrive, DejaReparti;
669 const Standard_Integer RejectIndexMAX = 250000;
670 Standard_Integer IncKey, RejectIndex;
673 DejaReparti = Standard_False;
677 previousPoint = myIntersectionOn2S.Point();
678 previoustg = Standard_False;
679 previousd = myIntersectionOn2S.Direction();
680 previousd1 = myIntersectionOn2S.DirectionOnS1();
681 previousd2 = myIntersectionOn2S.DirectionOnS2();
684 firstd1 = previousd1;
685 firstd2 = previousd2;
686 tgfirst = tglast = Standard_False;
687 choixIsoSav = ChoixIso;
688 //------------------------------------------------------------
689 //-- Test if the first point of marching corresponds
690 //-- to a point on borders.
691 //-- In this case, DejaReparti is initialized as True
693 pf = previousPoint.Value();
694 Standard_Boolean bTestFirstPoint = Standard_True;
696 previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
697 AddAPoint(line,previousPoint);
699 IntWalk_StatusDeflection Status = IntWalk_OK;
700 Standard_Boolean NoTestDeflection = Standard_False;
701 Standard_Real SvParam[4], f;
702 Standard_Integer LevelOfEmptyInmyIntersectionOn2S=0;
703 Standard_Integer LevelOfPointConfondu = 0;
704 Standard_Integer LevelOfIterWithoutAppend = -1;
706 Arrive = Standard_False;
709 LevelOfIterWithoutAppend++;
710 if(LevelOfIterWithoutAppend>20)
712 Arrive = Standard_True;
716 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
717 LevelOfIterWithoutAppend = 0;
723 case IntImp_UIsoparametricOnCaro1: f = Abs(previousd1.X()); break;
724 case IntImp_VIsoparametricOnCaro1: f = Abs(previousd1.Y()); break;
725 case IntImp_UIsoparametricOnCaro2: f = Abs(previousd2.X()); break;
726 case IntImp_VIsoparametricOnCaro2: f = Abs(previousd2.Y()); break;
734 previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
737 Standard_Real aIncKey, aEps, dP1, dP2, dP3, dP4;
739 dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
740 dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
741 dP3 = sensCheminement * pasuv[2] * previousd2.X() /f;
742 dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
744 aIncKey=5.*(Standard_Real)IncKey;
746 if(ChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < aEps)
751 if(ChoixIso == IntImp_VIsoparametricOnCaro1 && Abs(dP2) < aEps)
756 if(ChoixIso == IntImp_UIsoparametricOnCaro2 && Abs(dP3) < aEps)
761 if(ChoixIso == IntImp_VIsoparametricOnCaro2 && Abs(dP4) < aEps)
771 //==========================
777 ChoixIso= myIntersectionOn2S.Perform(Param, Rsnld, ChoixIso);
779 if (!myIntersectionOn2S.IsDone())
781 //end of line, division
782 Arrive = Standard_False;
787 RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
791 //== Calculation of exact point from Param(.) is possible
792 if (myIntersectionOn2S.IsEmpty())
794 Standard_Real u1,v1,u2,v2;
795 previousPoint.Parameters(u1,v1,u2,v2);
797 Arrive = Standard_False;
798 if(u1<UFirst1 || u1>ULast1)
800 Arrive=Standard_True;
803 if(u2<UFirst2 || u2>ULast2)
805 Arrive=Standard_True;
808 if(v1<VFirst1 || v1>VLast1)
810 Arrive=Standard_True;
813 if(v2<VFirst2 || v2>VLast2)
815 Arrive=Standard_True;
818 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
819 LevelOfEmptyInmyIntersectionOn2S++;
821 if(LevelOfEmptyInmyIntersectionOn2S>10)
831 //============================================================
832 //== A point has been found : T E S T D E F L E C T I O N
833 //============================================================
836 NoTestDeflection = Standard_False;
840 if(--LevelOfEmptyInmyIntersectionOn2S<=0)
842 LevelOfEmptyInmyIntersectionOn2S=0;
843 if(LevelOfIterWithoutAppend < 10)
845 Status = TestDeflection();
857 //============================================================
858 //== T r a i t e m e n t s u r S t a t u s ==
859 //============================================================
860 if(LevelOfPointConfondu > 5)
862 Status = IntWalk_ArretSurPoint;
863 LevelOfPointConfondu = 0;
866 if(Status==IntWalk_OK)
869 if(NbPasOKConseq >= 5)
872 Standard_Boolean pastroppetit;
877 pastroppetit=Standard_True;
879 if(pasuv[0]<pasInit[0])
881 t = (pasInit[0]-pasuv[0])*0.25;
888 pastroppetit=Standard_False;
891 if(pasuv[1]<pasInit[1])
893 t = (pasInit[1]-pasuv[1])*0.25;
894 if(t>0.1*pasInit[1]) {
899 pastroppetit=Standard_False;
902 if(pasuv[2]<pasInit[2])
904 t = (pasInit[2]-pasuv[2])*0.25;
911 pastroppetit=Standard_False;
914 if(pasuv[3]<pasInit[3])
916 t = (pasInit[3]-pasuv[3])*0.25;
917 if(t>0.1*pasInit[3]) {
921 pastroppetit=Standard_False;
935 pastroppetit=Standard_False;
941 }//Status==IntWalk_OK
948 case IntWalk_ArretSurPointPrecedent:
950 Arrive = Standard_False;
951 RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
954 case IntWalk_PasTropGrand:
961 if(LevelOfIterWithoutAppend > 5)
963 if(pasSav[0]<pasInit[0])
965 pasInit[0]-=(pasInit[0]-pasSav[0])*0.25;
966 LevelOfIterWithoutAppend=0;
969 if(pasSav[1]<pasInit[1])
971 pasInit[1]-=(pasInit[1]-pasSav[1])*0.25;
972 LevelOfIterWithoutAppend=0;
975 if(pasSav[2]<pasInit[2])
977 pasInit[2]-=(pasInit[2]-pasSav[2])*0.25;
978 LevelOfIterWithoutAppend=0;
981 if(pasSav[3]<pasInit[3])
983 pasInit[3]-=(pasInit[3]-pasSav[3])*0.25;
984 LevelOfIterWithoutAppend=0;
990 case IntWalk_PointConfondu:
992 LevelOfPointConfondu++;
994 if(LevelOfPointConfondu>5)
996 Standard_Boolean pastroppetit;
1000 pastroppetit=Standard_True;
1002 if(pasuv[0]<pasInit[0])
1004 pasuv[0]+=(pasInit[0]-pasuv[0])*0.25;
1005 pastroppetit=Standard_False;
1008 if(pasuv[1]<pasInit[1])
1010 pasuv[1]+=(pasInit[1]-pasuv[1])*0.25;
1011 pastroppetit=Standard_False;
1014 if(pasuv[2]<pasInit[2])
1016 pasuv[2]+=(pasInit[2]-pasuv[2])*0.25;
1017 pastroppetit=Standard_False;
1020 if(pasuv[3]<pasInit[3])
1022 pasuv[3]+=(pasInit[3]-pasuv[3])*0.25;
1023 pastroppetit=Standard_False;
1038 pastroppetit=Standard_False;
1042 while(pastroppetit);
1048 case IntWalk_ArretSurPoint://006
1050 //=======================================================
1051 //== Stop Test t : Frame on Param(.) ==
1052 //=======================================================
1054 Arrive = TestArret(DejaReparti,Param,ChoixIso);
1055 // JMB 30th December 1999.
1056 // Some statement below should not be put in comment because they are useful.
1057 // See grid CTO 909 A1 which infinitely loops
1058 if(Arrive==Standard_False && Status==IntWalk_ArretSurPoint)
1060 Arrive=Standard_True;
1062 cout << "Compile with option DEB : if problems with intersection : ";
1063 cout << "IntWalk_PWalking_1.gxx (lbr le 1erdec98)"<<endl;
1069 NbPasOKConseq = -10;
1074 //=====================================================
1075 //== Param(.) is in the limits ==
1076 //== and does not end a closed line ==
1077 //=====================================================
1078 //== Check on the current point of myInters
1079 Standard_Boolean pointisvalid = Standard_False;
1081 Standard_Real u1,v1,u2,v2;
1082 myIntersectionOn2S.Point().Parameters(u1,v1,u2,v2);
1085 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1086 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1087 v1 >= Vm1 && v2 >= Vm2)
1089 pointisvalid=Standard_True;
1096 previousPoint = myIntersectionOn2S.Point();
1097 previoustg = myIntersectionOn2S.IsTangent();
1101 previousd = myIntersectionOn2S.Direction();
1102 previousd1 = myIntersectionOn2S.DirectionOnS1();
1103 previousd2 = myIntersectionOn2S.DirectionOnS2();
1105 //=====================================================
1106 //== Check on the previous Point
1108 Standard_Real u1,v1,u2,v2;
1109 previousPoint.Parameters(u1,v1,u2,v2);
1110 if( u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1111 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1112 v1 >= Vm1 && v2 >= Vm2)
1114 pl = previousPoint.Value();
1117 if(pf.SquareDistance(pl) < aSQDistMax)
1127 bTestFirstPoint = Standard_False;
1131 AddAPoint(line,previousPoint);
1134 if(RejectIndex >= RejectIndexMAX)
1140 LevelOfIterWithoutAppend = 0;
1144 //====================================================
1146 if(Status == IntWalk_ArretSurPoint)
1148 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1152 if (line->NbPoints() == 2)
1154 pasSav[0] = pasuv[0];
1155 pasSav[1] = pasuv[1];
1156 pasSav[2] = pasuv[2];
1157 pasSav[3] = pasuv[3];
1165 //================= la ligne est fermee ===============
1166 AddAPoint(line,line->Value(1)); //ligne fermee
1167 LevelOfIterWithoutAppend=0;
1171 //====================================================
1172 //== Param was not in the limits (was reframed)
1173 //====================================================
1174 Standard_Boolean bPrevNotTangent = !previoustg || !myIntersectionOn2S.IsTangent();
1176 IntImp_ConstIsoparametric SauvChoixIso = ChoixIso;
1177 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld,ChoixIso);
1179 if(!myIntersectionOn2S.IsEmpty()) //002
1181 // mutially outpasses in the square or intersection in corner
1183 if(TestArret(Standard_True,Param,ChoixIso))
1185 NbPasOKConseq = -10;
1186 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld,ChoixIso);
1188 if(!myIntersectionOn2S.IsEmpty())
1190 previousPoint = myIntersectionOn2S.Point();
1191 previoustg = myIntersectionOn2S.IsTangent();
1195 previousd = myIntersectionOn2S.Direction();
1196 previousd1 = myIntersectionOn2S.DirectionOnS1();
1197 previousd2 = myIntersectionOn2S.DirectionOnS2();
1200 pl = previousPoint.Value();
1204 if(pf.SquareDistance(pl) < aSQDistMax)
1214 bTestFirstPoint = Standard_False;
1218 AddAPoint(line,previousPoint);
1221 if(RejectIndex >= RejectIndexMAX)
1227 LevelOfIterWithoutAppend=0;
1228 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1232 //fail framing divides the step
1233 Arrive = Standard_False;
1234 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1235 NoTestDeflection = Standard_True;
1236 ChoixIso = SauvChoixIso;
1241 // save the last point
1242 // to revert to it if the current point is out of bounds
1244 IntSurf_PntOn2S previousPointSave = previousPoint;
1245 Standard_Boolean previoustgSave = previoustg;
1246 gp_Dir previousdSave = previousd;
1247 gp_Dir2d previousd1Save = previousd1;
1248 gp_Dir2d previousd2Save = previousd2;
1250 previousPoint = myIntersectionOn2S.Point();
1251 previoustg = myIntersectionOn2S.IsTangent();
1252 Arrive = Standard_False;
1256 previousd = myIntersectionOn2S.Direction();
1257 previousd1 = myIntersectionOn2S.DirectionOnS1();
1258 previousd2 = myIntersectionOn2S.DirectionOnS2();
1261 //========================================
1262 //== Check on PreviousPoint @@
1265 Standard_Real u1,v1,u2,v2;
1266 previousPoint.Parameters(u1,v1,u2,v2);
1268 //To save initial 2d points
1269 gp_Pnt2d ParamPntOnS1(Param(1), Param(2));
1270 gp_Pnt2d ParamPntOnS2(Param(3), Param(4));
1272 ///////////////////////////
1280 Standard_Boolean bFlag1, bFlag2;
1281 Standard_Real aTol2D=1.e-11;
1283 bFlag1=u1 >= Um1-aTol2D && v1 >= Vm1-aTol2D && u1 <= UM1+aTol2D && v1 <= VM1+aTol2D;
1284 bFlag2=u2 >= Um2-aTol2D && v2 >= Vm2-aTol2D && u2 <= UM2+aTol2D && v2 <= VM2+aTol2D;
1285 if (bFlag1 && bFlag2)
1288 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1289 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1290 v1 >= Vm1 && v2 >= Vm2) {
1293 pl = previousPoint.Value();
1297 if(pf.SquareDistance(pl) < aSQDistMax)
1308 bTestFirstPoint = Standard_False;
1312 //To avoid walking around the same point
1313 //in the tangent zone near a border
1317 Standard_Real prevU1, prevV1, prevU2, prevV2;
1318 previousPointSave.Parameters(prevU1, prevV1, prevU2, prevV2);
1319 gp_Pnt2d prevPntOnS1(prevU1, prevV1), prevPntOnS2(prevU2, prevV2);
1320 gp_Pnt2d curPntOnS1(u1, v1), curPntOnS2(u2, v2);
1321 gp_Vec2d PrevToParamOnS1(prevPntOnS1, ParamPntOnS1);
1322 gp_Vec2d PrevToCurOnS1(prevPntOnS1, curPntOnS1);
1323 gp_Vec2d PrevToParamOnS2(prevPntOnS2, ParamPntOnS2);
1324 gp_Vec2d PrevToCurOnS2(prevPntOnS2, curPntOnS2);
1325 Standard_Real MaxAngle = 3*M_PI/4;
1327 if (Abs(PrevToParamOnS1.Angle(PrevToCurOnS1)) > MaxAngle &&
1328 Abs(PrevToParamOnS2.Angle(PrevToCurOnS2)) > MaxAngle)
1330 Arrive = Standard_True;
1335 ////////////////////////////////////////
1336 AddAPoint(line,previousPoint);
1339 if(RejectIndex >= RejectIndexMAX)
1346 LevelOfIterWithoutAppend=0;
1347 Arrive = Standard_True;
1351 // revert to the last correctly calculated point
1352 previousPoint = previousPointSave;
1353 previoustg = previoustgSave;
1354 previousd = previousdSave;
1355 previousd1 = previousd1Save;
1356 previousd2 = previousd2Save;
1361 Standard_Boolean wasExtended = Standard_False;
1363 if(Arrive && myIntersectionOn2S.IsTangent() && bPrevNotTangent)
1365 if(ExtendLineInCommonZone(SauvChoixIso, DejaReparti))
1367 wasExtended = Standard_True;
1368 Arrive = Standard_False;
1369 ChoixIso = SauvChoixIso;
1373 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1376 myIntersectionOn2S.IsDone() && !myIntersectionOn2S.IsEmpty() &&
1377 myIntersectionOn2S.IsTangent() && bPrevNotTangent &&
1380 if(ExtendLineInCommonZone(SauvChoixIso, DejaReparti))
1382 wasExtended = Standard_True;
1383 Arrive = Standard_False;
1384 ChoixIso = SauvChoixIso;
1387 }//else !TestArret() $
1388 }//$$ end successful framing on border (!myIntersectionOn2S.IsEmpty())
1391 //echec framing on border; division of step
1392 Arrive = Standard_False;
1393 NoTestDeflection = Standard_True;
1394 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1396 }//$$$ end framing on border (!close)
1397 }//004 fin TestArret return Arrive = True
1398 } // 006case IntWalk_ArretSurPoint: end Processing Status = OK or ArretSurPoint
1399 } //007 switch(Status)
1400 } //008 end processing point (TEST DEFLECTION)
1401 } //009 end processing line (else if myIntersectionOn2S.IsDone())
1402 } //010 end if first departure point allows marching while (!Arrive)
1404 done = Standard_True;
1406 // ===========================================================================================================
1407 // function: ExtendLineInCommonZone
1408 // purpose: Extends already computed line inside tangent zone in the direction given by theChoixIso.
1409 // Returns Standard_True if the line was extended through tangent zone and the last computed point
1410 // is outside the tangent zone (but it is not put into the line). Otherwise returns Standard_False.
1411 // ===========================================================================================================
1412 Standard_Boolean IntWalk_PWalking::ExtendLineInCommonZone(const IntImp_ConstIsoparametric theChoixIso,
1413 const Standard_Boolean theDirectionFlag)
1415 Standard_Boolean bOutOfTangentZone = Standard_False;
1416 Standard_Boolean bStop = !myIntersectionOn2S.IsTangent();
1417 Standard_Integer dIncKey = 1;
1418 TColStd_Array1OfReal Param(1,4);
1419 IntWalk_StatusDeflection Status = IntWalk_OK;
1420 Standard_Integer nbIterWithoutAppend = 0;
1421 Standard_Integer nbEqualPoints = 0;
1422 Standard_Integer parit = 0;
1423 Standard_Integer uvit = 0;
1424 IntSurf_SequenceOfPntOn2S aSeqOfNewPoint;
1427 nbIterWithoutAppend++;
1429 if((nbIterWithoutAppend > 20) || (nbEqualPoints > 20)) {
1431 cout<<"Compile with option DEB:";
1432 cout<<"Infinite loop has detected. Stop iterations (IntWalk_PWalking_1.gxx)" << endl;
1434 bStop = Standard_True;
1437 Standard_Real f = 0.;
1439 switch (theChoixIso)
1441 case IntImp_UIsoparametricOnCaro1: f = Abs(previousd1.X()); break;
1442 case IntImp_VIsoparametricOnCaro1: f = Abs(previousd1.Y()); break;
1443 case IntImp_UIsoparametricOnCaro2: f = Abs(previousd2.X()); break;
1444 case IntImp_VIsoparametricOnCaro2: f = Abs(previousd2.Y()); break;
1449 previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
1451 Standard_Real dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
1452 Standard_Real dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
1453 Standard_Real dP3 = sensCheminement * pasuv[2] * previousd2.X() /f;
1454 Standard_Real dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
1456 if(theChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < 1.e-7) dP1 *= (5. * (Standard_Real)dIncKey);
1457 if(theChoixIso == IntImp_VIsoparametricOnCaro1 && Abs(dP2) < 1.e-7) dP2 *= (5. * (Standard_Real)dIncKey);
1458 if(theChoixIso == IntImp_UIsoparametricOnCaro2 && Abs(dP3) < 1.e-7) dP3 *= (5. * (Standard_Real)dIncKey);
1459 if(theChoixIso == IntImp_VIsoparametricOnCaro2 && Abs(dP4) < 1.e-7) dP4 *= (5. * (Standard_Real)dIncKey);
1465 Standard_Real SvParam[4];
1466 IntImp_ConstIsoparametric ChoixIso = theChoixIso;
1468 for(parit = 0; parit < 4; parit++) {
1469 SvParam[parit] = Param(parit+1);
1471 math_FunctionSetRoot Rsnld(myIntersectionOn2S.Function());
1472 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld, theChoixIso);
1474 if (!myIntersectionOn2S.IsDone()) {
1475 return bOutOfTangentZone;
1478 if (myIntersectionOn2S.IsEmpty()) {
1479 return bOutOfTangentZone;
1482 Status = TestDeflection();
1484 if(Status == IntWalk_OK) {
1486 for(uvit = 0; uvit < 4; uvit++) {
1487 if(pasuv[uvit] < pasInit[uvit]) {
1488 pasuv[uvit] = pasInit[uvit];
1494 case IntWalk_ArretSurPointPrecedent:
1496 bStop = Standard_True;
1497 bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1500 case IntWalk_PasTropGrand:
1502 for(parit = 0; parit < 4; parit++) {
1503 Param(parit+1) = SvParam[parit];
1505 Standard_Boolean bDecrease = Standard_False;
1507 for(uvit = 0; uvit < 4; uvit++) {
1508 if(pasSav[uvit] < pasInit[uvit]) {
1509 pasInit[uvit] -= (pasInit[uvit] - pasSav[uvit]) * 0.1;
1510 bDecrease = Standard_True;
1514 if(bDecrease) nbIterWithoutAppend--;
1517 case IntWalk_PointConfondu:
1519 for(uvit = 0; uvit < 4; uvit++) {
1520 if(pasuv[uvit] < pasInit[uvit]) {
1521 pasuv[uvit] += (pasInit[uvit] - pasuv[uvit]) * 0.1;
1527 case IntWalk_ArretSurPoint:
1530 bStop = TestArret(theDirectionFlag, Param, ChoixIso);
1535 Standard_Real u11,v11,u12,v12;
1536 myIntersectionOn2S.Point().Parameters(u11,v11,u12,v12);
1537 Standard_Real u21,v21,u22,v22;
1538 previousPoint.Parameters(u21,v21,u22,v22);
1540 if(((fabs(u11-u21) < ResoU1) && (fabs(v11-v21) < ResoV1)) ||
1541 ((fabs(u12-u22) < ResoU2) && (fabs(v12-v22) < ResoV2))) {
1550 bStop = bStop || !myIntersectionOn2S.IsTangent();
1551 bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1554 Standard_Boolean pointisvalid = Standard_False;
1555 Standard_Real u1,v1,u2,v2;
1556 myIntersectionOn2S.Point().Parameters(u1,v1,u2,v2);
1558 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1559 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1560 v1 >= Vm1 && v2 >= Vm2)
1561 pointisvalid = Standard_True;
1564 previousPoint = myIntersectionOn2S.Point();
1565 previoustg = myIntersectionOn2S.IsTangent();
1568 previousd = myIntersectionOn2S.Direction();
1569 previousd1 = myIntersectionOn2S.DirectionOnS1();
1570 previousd2 = myIntersectionOn2S.DirectionOnS2();
1572 Standard_Boolean bAddPoint = Standard_True;
1574 if(line->NbPoints() >= 1) {
1575 gp_Pnt pf = line->Value(1).Value();
1576 gp_Pnt pl = previousPoint.Value();
1578 if(pf.Distance(pl) < Precision::Confusion()) {
1580 if(dIncKey == 5000) return bOutOfTangentZone;
1581 else bAddPoint = Standard_False;
1586 aSeqOfNewPoint.Append(previousPoint);
1587 nbIterWithoutAppend = 0;
1591 if (line->NbPoints() == 2) {
1592 for(uvit = 0; uvit < 4; uvit++) {
1593 pasSav[uvit] = pasuv[uvit];
1597 if ( !pointisvalid ) {
1598 // decrease step if out of bounds
1599 // otherwise the same calculations will be
1600 // repeated several times
1601 if ( ( u1 > UM1 ) || ( u1 < Um1 ) )
1604 if ( ( v1 > VM1 ) || ( v1 < Vm1 ) )
1607 if ( ( u2 > UM2 ) || ( u2 < Um2 ) )
1610 if ( ( v2 > VM2 ) || ( v2 < Vm2 ) )
1615 if(close && (line->NbPoints() >= 1)) {
1617 if(!bOutOfTangentZone) {
1618 aSeqOfNewPoint.Append(line->Value(1)); // line end
1620 nbIterWithoutAppend = 0;
1623 ChoixIso = myIntersectionOn2S.Perform(Param, Rsnld, theChoixIso);
1625 if(myIntersectionOn2S.IsEmpty()) {
1626 bStop = !myIntersectionOn2S.IsTangent();
1627 bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1630 Standard_Boolean bAddPoint = Standard_True;
1631 Standard_Boolean pointisvalid = Standard_False;
1633 previousPoint = myIntersectionOn2S.Point();
1634 Standard_Real u1,v1,u2,v2;
1635 previousPoint.Parameters(u1,v1,u2,v2);
1637 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1638 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1639 v1 >= Vm1 && v2 >= Vm2)
1640 pointisvalid = Standard_True;
1644 if(line->NbPoints() >= 1) {
1645 gp_Pnt pf = line->Value(1).Value();
1646 gp_Pnt pl = previousPoint.Value();
1648 if(pf.Distance(pl) < Precision::Confusion()) {
1650 if(dIncKey == 5000) return bOutOfTangentZone;
1651 else bAddPoint = Standard_False;
1655 if(bAddPoint && !bOutOfTangentZone) {
1656 aSeqOfNewPoint.Append(previousPoint);
1657 nbIterWithoutAppend = 0;
1672 Standard_Boolean bExtendLine = Standard_False;
1673 Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.;
1675 Standard_Integer pit = 0;
1677 for(pit = 0; !bExtendLine && (pit < 2); pit++) {
1679 previousPoint.Parameters(u1,v1,u2,v2);
1681 if(aSeqOfNewPoint.Length() > 0)
1682 aSeqOfNewPoint.Value(aSeqOfNewPoint.Length()).Parameters(u1,v1,u2,v2);
1687 if(((u1 - Um1) < ResoU1) ||
1688 ((UM1 - u1) < ResoU1) ||
1689 ((u2 - Um2) < ResoU2) ||
1690 ((UM2 - u2) < ResoU2) ||
1691 ((v1 - Vm1) < ResoV1) ||
1692 ((VM1 - v1) < ResoV1) ||
1693 ((v2 - Vm2) < ResoV2) ||
1694 ((VM2 - v2) < ResoV2))
1695 bExtendLine = Standard_True;
1699 // if(Status == IntWalk_OK || Status == IntWalk_ArretSurPoint) {
1700 if(Status == IntWalk_OK) {
1701 bExtendLine = Standard_True;
1703 if(aSeqOfNewPoint.Length() > 1) {
1704 TColStd_Array1OfReal FirstParams(0, 3), LastParams(0, 3), Resolutions(0, 3);
1705 Resolutions(0) = ResoU1; Resolutions(1) = ResoV1; Resolutions(2) = ResoU2; Resolutions(3) = ResoV2;
1707 aSeqOfNewPoint(1).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1708 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1709 aSeqOfNewPoint(aSeqOfNewPoint.Length()).Parameters(LastParams.ChangeValue(0),
1710 LastParams.ChangeValue(1),
1711 LastParams.ChangeValue(2),
1712 LastParams.ChangeValue(3));
1713 Standard_Integer indexofiso = 0;
1715 if(theChoixIso == IntImp_UIsoparametricOnCaro1) indexofiso = 0;
1716 if(theChoixIso == IntImp_VIsoparametricOnCaro1) indexofiso = 1;
1717 if(theChoixIso == IntImp_UIsoparametricOnCaro2) indexofiso = 2;
1718 if(theChoixIso == IntImp_VIsoparametricOnCaro2) indexofiso = 3;
1720 Standard_Integer afirstindex = (indexofiso < 2) ? 0 : 2;
1721 gp_Vec2d aTangentZoneDir(gp_Pnt2d(FirstParams.Value(afirstindex), FirstParams.Value(afirstindex + 1)),
1722 gp_Pnt2d(LastParams.Value(afirstindex), LastParams.Value(afirstindex + 1)));
1724 gp_Dir2d anIsoDir(0, 1);
1726 if((indexofiso == 1) || (indexofiso == 3))
1727 anIsoDir = gp_Dir2d(1, 0);
1729 if(aTangentZoneDir.SquareMagnitude() > gp::Resolution()) {
1730 Standard_Real piquota = M_PI*0.25;
1732 if(fabs(aTangentZoneDir.Angle(anIsoDir)) > piquota) {
1733 Standard_Integer ii = 1, nextii = 2;
1735 Standard_Real asqresol = gp::Resolution();
1736 asqresol *= asqresol;
1739 aSeqOfNewPoint(ii).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1740 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1741 aSeqOfNewPoint(ii + 1).Parameters(LastParams.ChangeValue(0), LastParams.ChangeValue(1),
1742 LastParams.ChangeValue(2), LastParams.ChangeValue(3));
1743 d1 = gp_Vec2d(gp_Pnt2d(FirstParams.Value(afirstindex),
1744 FirstParams.Value(afirstindex + 1)),
1745 gp_Pnt2d(LastParams.Value(afirstindex),
1746 LastParams.Value(afirstindex + 1)));
1749 while((d1.SquareMagnitude() < asqresol) &&
1750 (ii < aSeqOfNewPoint.Length()));
1754 while(nextii < aSeqOfNewPoint.Length()) {
1756 gp_Vec2d nextd1(0, 0);
1757 Standard_Integer jj = nextii;
1760 aSeqOfNewPoint(jj).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1761 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1762 aSeqOfNewPoint(jj + 1).Parameters(LastParams.ChangeValue(0), LastParams.ChangeValue(1),
1763 LastParams.ChangeValue(2), LastParams.ChangeValue(3));
1764 nextd1 = gp_Vec2d(gp_Pnt2d(FirstParams.Value(afirstindex),
1765 FirstParams.Value(afirstindex + 1)),
1766 gp_Pnt2d(LastParams.Value(afirstindex),
1767 LastParams.Value(afirstindex + 1)));
1771 while((nextd1.SquareMagnitude() < asqresol) &&
1772 (jj < aSeqOfNewPoint.Length()));
1775 if(fabs(d1.Angle(nextd1)) > piquota) {
1776 bExtendLine = Standard_False;
1782 // end if(fabs(aTangentZoneDir.Angle(anIsoDir)
1789 return Standard_False;
1791 Standard_Integer i = 0;
1793 for(i = 1; i <= aSeqOfNewPoint.Length(); i++) {
1794 AddAPoint(line, aSeqOfNewPoint.Value(i));
1797 return bOutOfTangentZone;
1800 //=======================================================================
1801 //function : DistanceMinimizeByGradient
1803 //=======================================================================
1804 Standard_Boolean IntWalk_PWalking::
1805 DistanceMinimizeByGradient( const Handle(Adaptor3d_HSurface)& theASurf1,
1806 const Handle(Adaptor3d_HSurface)& theASurf2,
1807 Standard_Real& theU1,
1808 Standard_Real& theV1,
1809 Standard_Real& theU2,
1810 Standard_Real& theV2,
1811 const Standard_Real theStep0U1V1,
1812 const Standard_Real theStep0U2V2)
1814 const Standard_Integer aNbIterMAX = 60;
1815 const Standard_Real aTol = 1.0e-14;
1816 Handle(Geom_Surface) aS1, aS2;
1818 switch(theASurf1->GetType())
1820 case GeomAbs_BezierSurface:
1821 aS1 = theASurf1->Surface().Bezier();
1823 case GeomAbs_BSplineSurface:
1824 aS1 = theASurf1->Surface().BSpline();
1827 return Standard_True;
1830 switch(theASurf2->GetType())
1832 case GeomAbs_BezierSurface:
1833 aS2 = theASurf2->Surface().Bezier();
1835 case GeomAbs_BSplineSurface:
1836 aS2 = theASurf2->Surface().BSpline();
1839 return Standard_True;
1842 Standard_Boolean aStatus = Standard_False;
1845 gp_Vec aD1u, aD1v, aD2U, aD2V;
1847 aS1->D1(theU1, theV1, aP1, aD1u, aD1v);
1848 aS2->D1(theU2, theV2, aP2, aD2U, aD2V);
1850 Standard_Real aSQDistPrev = aP1.SquareDistance(aP2);
1852 gp_Vec aP12(aP1, aP2);
1854 Standard_Real aGradFu(-aP12.Dot(aD1u));
1855 Standard_Real aGradFv(-aP12.Dot(aD1v));
1856 Standard_Real aGradFU( aP12.Dot(aD2U));
1857 Standard_Real aGradFV( aP12.Dot(aD2V));
1859 Standard_Real aSTEPuv = theStep0U1V1, aStepUV = theStep0U2V2;
1861 Standard_Boolean flRepeat = Standard_True;
1862 Standard_Integer aNbIter = aNbIterMAX;
1866 Standard_Real anAdd = aGradFu*aSTEPuv;
1867 Standard_Real aPARu = (anAdd >= 0.0)?
1868 (theU1 - Max(anAdd, Epsilon(theU1))) :
1869 (theU1 + Max(-anAdd, Epsilon(theU1)));
1870 anAdd = aGradFv*aSTEPuv;
1871 Standard_Real aPARv = (anAdd >= 0.0)?
1872 (theV1 - Max(anAdd, Epsilon(theV1))) :
1873 (theV1 + Max(-anAdd, Epsilon(theV1)));
1874 anAdd = aGradFU*aStepUV;
1875 Standard_Real aParU = (anAdd >= 0.0)?
1876 (theU2 - Max(anAdd, Epsilon(theU2))) :
1877 (theU2 + Max(-anAdd, Epsilon(theU2)));
1878 anAdd = aGradFV*aStepUV;
1879 Standard_Real aParV = (anAdd >= 0.0)?
1880 (theV2 - Max(anAdd, Epsilon(theV2))) :
1881 (theV2 + Max(-anAdd, Epsilon(theV2)));
1885 aS1->D1(aPARu, aPARv, aPt1, aD1u, aD1v);
1886 aS2->D1(aParU, aParV, aPt2, aD2U, aD2V);
1888 Standard_Real aSQDist = aPt1.SquareDistance(aPt2);
1890 if(aSQDist < aSQDistPrev)
1892 aSQDistPrev = aSQDist;
1898 aStatus = aSQDistPrev < aTol;
1906 flRepeat = Standard_False;
1910 aS1->D1(theU1, theV1, aPt1, aD1u, aD1v);
1911 aS2->D1(theU2, theV2, aPt2, aD2U, aD2V);
1913 gp_Vec aP12(aPt1, aPt2);
1914 aGradFu = -aP12.Dot(aD1u);
1915 aGradFv = -aP12.Dot(aD1v);
1916 aGradFU = aP12.Dot(aD2U);
1917 aGradFV = aP12.Dot(aD2V);
1918 aSTEPuv = theStep0U1V1;
1919 aStepUV = theStep0U2V2;
1927 //=======================================================================
1928 //function : DistanceMinimizeByExtrema
1930 //=======================================================================
1931 Standard_Boolean IntWalk_PWalking::
1932 DistanceMinimizeByExtrema(const Handle(Adaptor3d_HSurface)& theASurf,
1933 const gp_Pnt& theP0,
1934 Standard_Real& theU0,
1935 Standard_Real& theV0,
1936 const Standard_Real theStep0U,
1937 const Standard_Real theStep0V)
1939 const Standard_Real aTol = 1.0e-14;
1941 gp_Vec aD1Su, aD1Sv, aD2Su, aD2Sv, aD2SuvTemp;
1942 Standard_Real aSQDistPrev = RealLast();
1943 Standard_Real aU = theU0, aV = theV0;
1945 Standard_Integer aNbIter = 10;
1948 theASurf->D2(aU, aV, aPS, aD1Su, aD1Sv, aD2Su, aD2Sv, aD2SuvTemp);
1950 gp_Vec aVec(theP0, aPS);
1952 Standard_Real aSQDist = aVec.SquareMagnitude();
1954 if(aSQDist >= aSQDistPrev)
1957 aSQDistPrev = aSQDist;
1962 if(aSQDistPrev < aTol)
1966 const Standard_Real aF1 = aD1Su.Dot(aVec), aF2 = aD1Sv.Dot(aVec);
1969 const Standard_Real aDf1u = aD2Su.Dot(aVec) + aD1Su.Dot(aD1Su),
1970 aDf1v = aD2Su.Dot(aD1Sv),
1972 aDf2v = aD2Sv.Dot(aVec) + aD1Sv.Dot(aD1Sv);
1974 const Standard_Real aDet = aDf1u*aDf2v - aDf1v*aDf2u;
1975 aU -= theStep0U*(aDf2v*aF1 - aDf1v*aF2)/aDet;
1976 aV += theStep0V*(aDf2u*aF1 - aDf1u*aF2)/aDet;
1980 return (aSQDistPrev < aTol);
1983 //=======================================================================
1984 //function : SeekPointOnBoundary
1986 //=======================================================================
1987 Standard_Boolean IntWalk_PWalking::
1988 SeekPointOnBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
1989 const Handle(Adaptor3d_HSurface)& theASurf2,
1990 const Standard_Real theU1,
1991 const Standard_Real theV1,
1992 const Standard_Real theU2,
1993 const Standard_Real theV2,
1994 const Standard_Boolean isTheFirst)
1996 const Standard_Real aTol = 1.0e-14;
1997 Standard_Boolean isOK = Standard_False;
1998 Standard_Real U1prec = theU1, V1prec = theV1, U2prec = theU2, V2prec = theV2;
2000 Standard_Boolean flFinish = Standard_False;
2002 Standard_Integer aNbIter = 20;
2005 flFinish = Standard_False;
2006 Standard_Boolean aStatus = Standard_False;
2011 aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec);
2017 aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(U2prec, V2prec), U1prec, V1prec);
2023 aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(U1prec, V1prec), U2prec, V2prec);
2029 while(!aStatus && (aNbIter > 0));
2033 const Standard_Real aTolMax = 1.0e-8;
2034 Standard_Real aTolF = 0.0;
2036 Standard_Real u1 = U1prec, v1 = V1prec, u2 = U2prec, v2 = V2prec;
2038 flFinish = Checking(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec, aTolF);
2040 if(aTolF <= aTolMax)
2042 gp_Pnt aP1 = theASurf1->Value(u1, v1),
2043 aP2 = theASurf2->Value(u2, v2);
2044 gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2046 const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
2047 aSQDist2 = aPInt.SquareDistance(aP2);
2048 if((aSQDist1 < aTol) && (aSQDist2 < aTol))
2050 IntSurf_PntOn2S anIP;
2051 anIP.SetValue(aPInt, u1, v1, u2, v2);
2054 line->InsertBefore(1,anIP);
2058 isOK = Standard_True;
2074 //=======================================================================
2075 //function : PutToBoundary
2077 //=======================================================================
2078 Standard_Boolean IntWalk_PWalking::
2079 PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
2080 const Handle(Adaptor3d_HSurface)& theASurf2)
2082 const Standard_Real aTolMin = Precision::Confusion();
2084 Standard_Boolean hasBeenAdded = Standard_False;
2086 const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
2087 const Standard_Real aU1bLast = theASurf1->LastUParameter();
2088 const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
2089 const Standard_Real aU2bLast = theASurf2->LastUParameter();
2090 const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
2091 const Standard_Real aV1bLast = theASurf1->LastVParameter();
2092 const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
2093 const Standard_Real aV2bLast = theASurf2->LastVParameter();
2095 Standard_Real aTol = 1.0;
2096 aTol = Min(aTol, aU1bLast - aU1bFirst);
2097 aTol = Min(aTol, aU2bLast - aU2bFirst);
2098 aTol = Min(aTol, aV1bLast - aV1bFirst);
2099 aTol = Min(aTol, aV2bLast - aV2bFirst)*1.0e-3;
2101 if(aTol <= 2.0*aTolMin)
2102 return hasBeenAdded;
2104 Standard_Boolean isNeedAdding = Standard_False;
2105 Standard_Boolean isU1parallel = Standard_False, isV1parallel = Standard_False;
2106 Standard_Boolean isU2parallel = Standard_False, isV2parallel = Standard_False;
2107 IsParallel(line, Standard_True, aTol, isU1parallel, isV1parallel);
2108 IsParallel(line, Standard_False, aTol, isU2parallel, isV2parallel);
2110 const Standard_Integer aNbPnts = line->NbPoints();
2111 Standard_Real u1, v1, u2, v2;
2112 line->Value(1).Parameters(u1, v1, u2, v2);
2113 Standard_Real aDelta = 0.0;
2117 aDelta = u1 - aU1bFirst;
2118 if((aTolMin < aDelta) && (aDelta < aTol))
2120 u1 = aU1bFirst - aDelta;
2121 isNeedAdding = Standard_True;
2125 aDelta = aU1bLast - u1;
2126 if((aTolMin < aDelta) && (aDelta < aTol))
2128 u1 = aU1bLast + aDelta;
2129 isNeedAdding = Standard_True;
2136 aDelta = u2 - aU2bFirst;
2137 if((aTolMin < aDelta) && (aDelta < aTol))
2139 u2 = aU2bFirst - aDelta;
2140 isNeedAdding = Standard_True;
2144 aDelta = aU2bLast - u2;
2145 if((aTolMin < aDelta) && (aDelta < aTol))
2147 u2 = aU2bLast + aDelta;
2148 isNeedAdding = Standard_True;
2155 aDelta = v1 - aV1bFirst;
2156 if((aTolMin < aDelta) && (aDelta < aTol))
2158 v1 = aV1bFirst - aDelta;
2159 isNeedAdding = Standard_True;
2163 aDelta = aV1bLast - v1;
2164 if((aTolMin < aDelta) && (aDelta < aTol))
2166 v1 = aV1bLast + aDelta;
2167 isNeedAdding = Standard_True;
2174 aDelta = v2 - aV2bFirst;
2175 if((aTolMin < aDelta) && (aDelta < aTol))
2177 v2 = aV2bFirst - aDelta;
2178 isNeedAdding = Standard_True;
2182 aDelta = aV2bLast - v2;
2183 if((aTolMin < aDelta) && (aDelta < aTol))
2185 v2 = aV2bLast + aDelta;
2186 isNeedAdding = Standard_True;
2194 SeekPointOnBoundary(theASurf1, theASurf2, u1,
2195 v1, u2, v2, Standard_True);
2198 isNeedAdding = Standard_False;
2199 line->Value(aNbPnts).Parameters(u1, v1, u2, v2);
2203 aDelta = u1 - aU1bFirst;
2204 if((aTolMin < aDelta) && (aDelta < aTol))
2206 u1 = aU1bFirst - aDelta;
2207 isNeedAdding = Standard_True;
2211 aDelta = aU1bLast - u1;
2212 if((aTolMin < aDelta) && (aDelta < aTol))
2214 u1 = aU1bLast + aDelta;
2215 isNeedAdding = Standard_True;
2222 aDelta = u2 - aU2bFirst;
2223 if((aTolMin < aDelta) && (aDelta < aTol))
2225 u2 = aU2bFirst - aDelta;
2226 isNeedAdding = Standard_True;
2230 aDelta = aU2bLast - u2;
2231 if((aTolMin < aDelta) && (aDelta < aTol))
2233 u2 = aU2bLast + aDelta;
2234 isNeedAdding = Standard_True;
2241 aDelta = v1 - aV1bFirst;
2242 if((aTolMin < aDelta) && (aDelta < aTol))
2244 v1 = aV1bFirst - aDelta;
2245 isNeedAdding = Standard_True;
2249 aDelta = aV1bLast - v1;
2250 if((aTolMin < aDelta) && (aDelta < aTol))
2252 v1 = aV1bLast + aDelta;
2253 isNeedAdding = Standard_True;
2260 aDelta = v2 - aV2bFirst;
2261 if((aTolMin < aDelta) && (aDelta < aTol))
2263 v2 = aV2bFirst - aDelta;
2264 isNeedAdding = Standard_True;
2268 aDelta = aV2bLast - v2;
2269 if((aTolMin < aDelta) && (aDelta < aTol))
2271 v2 = aV2bLast + aDelta;
2272 isNeedAdding = Standard_True;
2280 SeekPointOnBoundary(theASurf1, theASurf2, u1,
2281 v1, u2, v2, Standard_False);
2284 return hasBeenAdded;
2287 //=======================================================================
2288 //function : SeekAdditionalPoints
2290 //=======================================================================
2291 Standard_Boolean IntWalk_PWalking::
2292 SeekAdditionalPoints( const Handle(Adaptor3d_HSurface)& theASurf1,
2293 const Handle(Adaptor3d_HSurface)& theASurf2,
2294 const Standard_Integer theMinNbPoints)
2296 const Standard_Real aTol = 1.0e-14;
2297 Standard_Integer aNbPoints = line->NbPoints();
2298 if(aNbPoints > theMinNbPoints)
2299 return Standard_True;
2301 const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
2302 const Standard_Real aU1bLast = theASurf1->LastUParameter();
2303 const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
2304 const Standard_Real aU2bLast = theASurf2->LastUParameter();
2305 const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
2306 const Standard_Real aV1bLast = theASurf1->LastVParameter();
2307 const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
2308 const Standard_Real aV2bLast = theASurf2->LastVParameter();
2311 Standard_Boolean isPrecise = Standard_False;
2313 Standard_Real U1prec = 0.0, V1prec = 0.0, U2prec = 0.0, V2prec = 0.0;
2315 Standard_Integer aNbPointsPrev = 0;
2316 while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
2318 aNbPointsPrev = aNbPoints;
2319 for(Standard_Integer fp = 1, lp = 2; fp < aNbPoints; fp = lp + 1)
2321 Standard_Real U1f, V1f, U2f, V2f; //first point in 1st and 2nd surafaces
2322 Standard_Real U1l, V1l, U2l, V2l; //last point in 1st and 2nd surafaces
2325 line->Value(fp).Parameters(U1f, V1f, U2f, V2f);
2326 line->Value(lp).Parameters(U1l, V1l, U2l, V2l);
2328 U1prec = 0.5*(U1f+U1l);
2329 if(U1prec < aU1bFirst)
2331 if(U1prec > aU1bLast)
2334 V1prec = 0.5*(V1f+V1l);
2335 if(V1prec < aV1bFirst)
2337 if(V1prec > aV1bLast)
2340 U2prec = 0.5*(U2f+U2l);
2341 if(U2prec < aU2bFirst)
2343 if(U2prec > aU2bLast)
2346 V2prec = 0.5*(V2f+V2l);
2347 if(V2prec < aV2bFirst)
2349 if(V2prec > aV2bLast)
2352 Standard_Boolean aStatus = Standard_False;
2353 Standard_Integer aNbIter = 5;
2356 aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, U1prec, V1prec, U2prec, V2prec);
2362 aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(U2prec, V2prec), U1prec, V1prec);
2368 aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(U1prec, V1prec), U2prec, V2prec);
2374 while(!aStatus && (--aNbIter > 0));
2378 gp_Pnt aP1 = theASurf1->Value(U1prec, V1prec),
2379 aP2 = theASurf2->Value(U2prec, V2prec);
2380 gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2382 const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
2383 aSQDist2 = aPInt.SquareDistance(aP2);
2385 if((aSQDist1 < aTol) && (aSQDist2 < aTol))
2387 IntSurf_PntOn2S anIP;
2388 anIP.SetValue(aPInt, U1prec, V1prec, U2prec, V2prec);
2389 line->InsertBefore(lp, anIP);
2391 isPrecise = Standard_True;
2393 if(++aNbPoints >= theMinNbPoints)