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.
16 #include <Adaptor3d_HSurface.hxx>
17 #include <Adaptor3d_HSurfaceTool.hxx>
18 #include <Extrema_GenLocateExtPS.hxx>
19 #include <Geom_Surface.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <IntImp_ComputeTangence.hxx>
24 #include <IntSurf_LineOn2S.hxx>
25 #include <IntSurf_PntOn2S.hxx>
26 #include <IntWalk_PWalking.hxx>
27 #include <IntWalk_StatusDeflection.hxx>
28 #include <math_FunctionSetRoot.hxx>
29 #include <Precision.hxx>
30 #include <Standard_Failure.hxx>
31 #include <Standard_OutOfRange.hxx>
32 #include <StdFail_NotDone.hxx>
33 #include <TColgp_Array1OfPnt.hxx>
34 #include <TColStd_Array1OfReal.hxx>
36 //==================================================================================
37 // function : ComputePasInit
38 // purpose : estimate of max step : To avoid abrupt changes during change of isos
39 //==================================================================================
40 void IntWalk_PWalking::ComputePasInit(const Standard_Real theDeltaU1,
41 const Standard_Real theDeltaV1,
42 const Standard_Real theDeltaU2,
43 const Standard_Real theDeltaV2)
45 const Standard_Real aRangePart = 0.01;
46 const Standard_Real Increment = 2.0*pasMax;
47 const Handle(Adaptor3d_HSurface)&
48 Caro1 = myIntersectionOn2S.Function().AuxillarSurface1();
49 const Handle(Adaptor3d_HSurface)&
50 Caro2 = myIntersectionOn2S.Function().AuxillarSurface2();
52 const Standard_Real aDeltaU1=Abs(UM1-Um1);
53 const Standard_Real aDeltaV1=Abs(VM1-Vm1);
54 const Standard_Real aDeltaU2=Abs(UM2-Um2);
55 const Standard_Real aDeltaV2=Abs(VM2-Vm2);
57 //-- limit the reduction of uv box estimate to 0.01 natural box
58 //-- theDeltaU1 : On box of Inter
59 //-- aDeltaU1 : On parametric space
60 if(!Precision::IsInfinite(aDeltaU1))
61 pasuv[0]=Max(Increment*Max(theDeltaU1, aRangePart*aDeltaU1), pasuv[0]);
63 pasuv[0]=Max(Increment*theDeltaU1, pasuv[0]);
65 if(!Precision::IsInfinite(aDeltaV1))
66 pasuv[1]=Max(Increment*Max(theDeltaV1, aRangePart*aDeltaV1), pasuv[1]);
68 pasuv[1]=Max(Increment*theDeltaV1, pasuv[1]);
70 if(!Precision::IsInfinite(aDeltaU2))
71 pasuv[2]=Max(Increment*Max(theDeltaU2, aRangePart*aDeltaU2), pasuv[2]);
73 pasuv[2]=Max(Increment*theDeltaU2, pasuv[2]);
75 if(!Precision::IsInfinite(aDeltaV2))
76 pasuv[3]=Max(Increment*Max(theDeltaV2, aRangePart*aDeltaV2), pasuv[3]);
78 pasuv[3]=Max(Increment*theDeltaV2, pasuv[3]);
80 const Standard_Real ResoU1tol = Adaptor3d_HSurfaceTool::UResolution(Caro1, tolconf);
81 const Standard_Real ResoV1tol = Adaptor3d_HSurfaceTool::VResolution(Caro1, tolconf);
82 const Standard_Real ResoU2tol = Adaptor3d_HSurfaceTool::UResolution(Caro2, tolconf);
83 const Standard_Real ResoV2tol = Adaptor3d_HSurfaceTool::VResolution(Caro2, tolconf);
85 myStepMin[0] = Max(myStepMin[0], 2.0*ResoU1tol);
86 myStepMin[1] = Max(myStepMin[1], 2.0*ResoV1tol);
87 myStepMin[2] = Max(myStepMin[2], 2.0*ResoU2tol);
88 myStepMin[3] = Max(myStepMin[3], 2.0*ResoV2tol);
90 for(Standard_Integer i = 0; i < 4; i++)
92 pasuv[i]=Max(myStepMin[i], pasuv[i]);
96 //=======================================================================
97 //function : IsParallel
98 //purpose : Checks if theLine is parallel of some boundary of given
99 // surface (it is determined by theCheckSurf1 flag).
100 // Parallelism assumes small oscillations (swing is less or
101 // equal than theToler).
102 // Small lines (if first and last parameters in the Surface
103 // are almost equal) are classified as parallel (as same as
104 // any point can be considered as parallel of any line).
105 //=======================================================================
106 static void IsParallel(const Handle(IntSurf_LineOn2S)& theLine,
107 const Standard_Boolean theCheckSurf1,
108 const Standard_Real theToler,
109 Standard_Boolean& theIsUparallel,
110 Standard_Boolean& theIsVparallel)
112 const Standard_Integer aNbPointsMAX = 23;
114 theIsUparallel = theIsVparallel = Standard_True;
116 const Standard_Integer aNbLinePnts = theLine->NbPoints();
117 Standard_Integer aNbPoints = aNbLinePnts;
118 if(aNbPoints > aNbPointsMAX)
120 aNbPoints = aNbPointsMAX;
122 else if(aNbPoints < 3)
124 //Here we cannot estimate parallelism.
125 //Do all same as for small lines
129 Standard_Real aStep = IntToReal(theLine->NbPoints()) / aNbPoints;
130 Standard_Real aNPoint = 1.0;
132 Standard_Real aUmin = RealLast(), aUmax = RealFirst(), aVmin = RealLast(), aVmax = RealFirst();
133 for(Standard_Integer aNum = 1; aNum <= aNbPoints; aNum++, aNPoint += aStep)
135 // Fix possible "out of parameter" case.
136 if (aNPoint > aNbLinePnts)
137 aNPoint = aNbLinePnts;
141 theLine->Value(RealToInt(aNPoint)).ParametersOnS1(u, v);
143 theLine->Value(RealToInt(aNPoint)).ParametersOnS2(u, v);
158 theIsVparallel = ((aUmax - aUmin) < theToler);
159 theIsUparallel = ((aVmax - aVmin) < theToler);
162 //=======================================================================
163 //function : AdjustToDomain
164 //purpose : Returns TRUE if theP has been changed (i.e. initial value
165 // was out of the domain)
166 //=======================================================================
167 static Standard_Boolean AdjustToDomain(const Standard_Integer theNbElem,
168 Standard_Real* theParam,
169 const Standard_Real* const theLowBorder,
170 const Standard_Real* const theUppBorder)
172 Standard_Boolean aRetVal = Standard_False;
173 for (Standard_Integer i = 0; i < theNbElem; i++)
175 if ((theParam[i] - theLowBorder[i]) < -Precision::PConfusion())
177 theParam[i] = theLowBorder[i];
178 aRetVal = Standard_True;
181 if ((theParam[i] - theUppBorder[i]) > Precision::PConfusion())
183 theParam[i] = theUppBorder[i];
184 aRetVal = Standard_True;
191 //==================================================================================
192 // function : IntWalk_PWalking::IntWalk_PWalking
194 //==================================================================================
195 IntWalk_PWalking::IntWalk_PWalking(const Handle(Adaptor3d_HSurface)& Caro1,
196 const Handle(Adaptor3d_HSurface)& Caro2,
197 const Standard_Real TolTangency,
198 const Standard_Real Epsilon,
199 const Standard_Real Deflection,
200 const Standard_Real Increment )
204 close(Standard_False),
207 myTolTang(TolTangency),
209 myIntersectionOn2S(Caro1,Caro2,TolTangency),
210 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND(0),
211 STATIC_PRECEDENT_INFLEXION(0)
213 Standard_Real KELARG=20.;
215 pasMax=Increment*0.2; //-- June 25 99 after problems with precision
216 Um1 = Adaptor3d_HSurfaceTool::FirstUParameter(Caro1);
217 Vm1 = Adaptor3d_HSurfaceTool::FirstVParameter(Caro1);
218 UM1 = Adaptor3d_HSurfaceTool::LastUParameter(Caro1);
219 VM1 = Adaptor3d_HSurfaceTool::LastVParameter(Caro1);
221 Um2 = Adaptor3d_HSurfaceTool::FirstUParameter(Caro2);
222 Vm2 = Adaptor3d_HSurfaceTool::FirstVParameter(Caro2);
223 UM2 = Adaptor3d_HSurfaceTool::LastUParameter(Caro2);
224 VM2 = Adaptor3d_HSurfaceTool::LastVParameter(Caro2);
226 ResoU1 = Adaptor3d_HSurfaceTool::UResolution(Caro1,Precision::Confusion());
227 ResoV1 = Adaptor3d_HSurfaceTool::VResolution(Caro1,Precision::Confusion());
229 ResoU2 = Adaptor3d_HSurfaceTool::UResolution(Caro2,Precision::Confusion());
230 ResoV2 = Adaptor3d_HSurfaceTool::VResolution(Caro2,Precision::Confusion());
232 Standard_Real NEWRESO;
233 Standard_Real MAXVAL;
234 Standard_Real MAXVAL2;
236 MAXVAL = Abs(Um1); MAXVAL2 = Abs(UM1);
237 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
238 NEWRESO = ResoU1 * MAXVAL ;
239 if(NEWRESO > ResoU1 &&NEWRESO<10) { ResoU1 = NEWRESO; }
242 MAXVAL = Abs(Um2); MAXVAL2 = Abs(UM2);
243 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
244 NEWRESO = ResoU2 * MAXVAL ;
245 if(NEWRESO > ResoU2 && NEWRESO<10) { ResoU2 = NEWRESO; }
248 MAXVAL = Abs(Vm1); MAXVAL2 = Abs(VM1);
249 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
250 NEWRESO = ResoV1 * MAXVAL ;
251 if(NEWRESO > ResoV1 && NEWRESO<10) { ResoV1 = NEWRESO; }
254 MAXVAL = Abs(Vm2); MAXVAL2 = Abs(VM2);
255 if(MAXVAL2 > MAXVAL) MAXVAL = MAXVAL2;
256 NEWRESO = ResoV2 * MAXVAL ;
257 if(NEWRESO > ResoV2 && NEWRESO<10) { ResoV2 = NEWRESO; }
259 pasuv[0]=pasMax*Abs(UM1-Um1);
260 pasuv[1]=pasMax*Abs(VM1-Vm1);
261 pasuv[2]=pasMax*Abs(UM2-Um2);
262 pasuv[3]=pasMax*Abs(VM2-Vm2);
264 if(ResoU1>0.0001*pasuv[0]) ResoU1=0.00001*pasuv[0];
265 if(ResoV1>0.0001*pasuv[1]) ResoV1=0.00001*pasuv[1];
266 if(ResoU2>0.0001*pasuv[2]) ResoU2=0.00001*pasuv[2];
267 if(ResoV2>0.0001*pasuv[3]) ResoV2=0.00001*pasuv[3];
270 if(Adaptor3d_HSurfaceTool::IsUPeriodic(Caro1)==Standard_False) {
271 //UM1+=KELARG*pasuv[0]; Um1-=KELARG*pasuv[0];
274 Standard_Real t = UM1-Um1;
275 if(t<Adaptor3d_HSurfaceTool::UPeriod(Caro1)) {
276 t=0.5*(Adaptor3d_HSurfaceTool::UPeriod(Caro1)-t);
277 t=(t>KELARG*pasuv[0])? KELARG*pasuv[0] : t;
282 if(Adaptor3d_HSurfaceTool::IsVPeriodic(Caro1)==Standard_False) {
283 //VM1+=KELARG*pasuv[1]; Vm1-=KELARG*pasuv[1];
286 Standard_Real t = VM1-Vm1;
287 if(t<Adaptor3d_HSurfaceTool::VPeriod(Caro1)) {
288 t=0.5*(Adaptor3d_HSurfaceTool::VPeriod(Caro1)-t);
289 t=(t>KELARG*pasuv[1])? KELARG*pasuv[1] : t;
294 if(Adaptor3d_HSurfaceTool::IsUPeriodic(Caro2)==Standard_False) {
295 //UM2+=KELARG*pasuv[2]; Um2-=KELARG*pasuv[2];
298 Standard_Real t = UM2-Um2;
299 if(t<Adaptor3d_HSurfaceTool::UPeriod(Caro2)) {
300 t=0.5*(Adaptor3d_HSurfaceTool::UPeriod(Caro2)-t);
301 t=(t>KELARG*pasuv[2])? KELARG*pasuv[2] : t;
306 if(Adaptor3d_HSurfaceTool::IsVPeriodic(Caro2)==Standard_False) {
307 //VM2+=KELARG*pasuv[3]; Vm2-=KELARG*pasuv[3];
310 Standard_Real t = VM2-Vm2;
311 if(t<Adaptor3d_HSurfaceTool::VPeriod(Caro2)) {
312 t=0.5*(Adaptor3d_HSurfaceTool::VPeriod(Caro2)-t);
313 t=(t>KELARG*pasuv[3])? KELARG*pasuv[3] : t;
318 myStepMin[0] = 100.0*ResoU1;
319 myStepMin[1] = 100.0*ResoV1;
320 myStepMin[2] = 100.0*ResoU2;
321 myStepMin[3] = 100.0*ResoV2;
323 //-- ComputePasInit(pasuv,Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2);
325 for (Standard_Integer i = 0; i<=3;i++) {
328 pasInit[i] = pasSav[i] = pasuv[i];
333 //==================================================================================
334 // function : IntWalk_PWalking
336 //==================================================================================
337 IntWalk_PWalking::IntWalk_PWalking(const Handle(Adaptor3d_HSurface)& Caro1,
338 const Handle(Adaptor3d_HSurface)& Caro2,
339 const Standard_Real TolTangency,
340 const Standard_Real Epsilon,
341 const Standard_Real Deflection,
342 const Standard_Real Increment,
343 const Standard_Real U1,
344 const Standard_Real V1,
345 const Standard_Real U2,
346 const Standard_Real V2)
350 close(Standard_False),
353 myTolTang(TolTangency),
355 myIntersectionOn2S(Caro1,Caro2,TolTangency),
356 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND(0),
357 STATIC_PRECEDENT_INFLEXION(0)
359 Standard_Real KELARG=20.;
361 pasMax=Increment*0.2; //-- June 25 99 after problems with precision
363 Um1 = Adaptor3d_HSurfaceTool::FirstUParameter(Caro1);
364 Vm1 = Adaptor3d_HSurfaceTool::FirstVParameter(Caro1);
365 UM1 = Adaptor3d_HSurfaceTool::LastUParameter(Caro1);
366 VM1 = Adaptor3d_HSurfaceTool::LastVParameter(Caro1);
368 Um2 = Adaptor3d_HSurfaceTool::FirstUParameter(Caro2);
369 Vm2 = Adaptor3d_HSurfaceTool::FirstVParameter(Caro2);
370 UM2 = Adaptor3d_HSurfaceTool::LastUParameter(Caro2);
371 VM2 = Adaptor3d_HSurfaceTool::LastVParameter(Caro2);
373 ResoU1 = Adaptor3d_HSurfaceTool::UResolution(Caro1,Precision::Confusion());
374 ResoV1 = Adaptor3d_HSurfaceTool::VResolution(Caro1,Precision::Confusion());
376 ResoU2 = Adaptor3d_HSurfaceTool::UResolution(Caro2,Precision::Confusion());
377 ResoV2 = Adaptor3d_HSurfaceTool::VResolution(Caro2,Precision::Confusion());
379 Standard_Real NEWRESO, MAXVAL, MAXVAL2;
383 if(MAXVAL2 > MAXVAL) {
386 NEWRESO = ResoU1 * MAXVAL ;
387 if(NEWRESO > ResoU1) {
393 if(MAXVAL2 > MAXVAL){
396 NEWRESO = ResoU2 * MAXVAL ;
397 if(NEWRESO > ResoU2) {
403 if(MAXVAL2 > MAXVAL) {
406 NEWRESO = ResoV1 * MAXVAL ;
407 if(NEWRESO > ResoV1) {
413 if(MAXVAL2 > MAXVAL){
416 NEWRESO = ResoV2 * MAXVAL ;
417 if(NEWRESO > ResoV2) {
421 pasuv[0]=pasMax*Abs(UM1-Um1);
422 pasuv[1]=pasMax*Abs(VM1-Vm1);
423 pasuv[2]=pasMax*Abs(UM2-Um2);
424 pasuv[3]=pasMax*Abs(VM2-Vm2);
426 if(Adaptor3d_HSurfaceTool::IsUPeriodic(Caro1)==Standard_False) {
427 UM1+=KELARG*pasuv[0];
428 Um1-=KELARG*pasuv[0];
431 Standard_Real t = UM1-Um1;
432 if(t<Adaptor3d_HSurfaceTool::UPeriod(Caro1)) {
433 t=0.5*(Adaptor3d_HSurfaceTool::UPeriod(Caro1)-t);
434 t=(t>KELARG*pasuv[0])? KELARG*pasuv[0] : t;
440 if(Adaptor3d_HSurfaceTool::IsVPeriodic(Caro1)==Standard_False) {
441 VM1+=KELARG*pasuv[1];
442 Vm1-=KELARG*pasuv[1];
445 Standard_Real t = VM1-Vm1;
446 if(t<Adaptor3d_HSurfaceTool::VPeriod(Caro1)) {
447 t=0.5*(Adaptor3d_HSurfaceTool::VPeriod(Caro1)-t);
448 t=(t>KELARG*pasuv[1])? KELARG*pasuv[1] : t;
453 if(Adaptor3d_HSurfaceTool::IsUPeriodic(Caro2)==Standard_False) {
454 UM2+=KELARG*pasuv[2];
455 Um2-=KELARG*pasuv[2];
458 Standard_Real t = UM2-Um2;
459 if(t<Adaptor3d_HSurfaceTool::UPeriod(Caro2)) {
460 t=0.5*(Adaptor3d_HSurfaceTool::UPeriod(Caro2)-t);
461 t=(t>KELARG*pasuv[2])? KELARG*pasuv[2] : t;
467 if(Adaptor3d_HSurfaceTool::IsVPeriodic(Caro2)==Standard_False) {
468 VM2+=KELARG*pasuv[3];
469 Vm2-=KELARG*pasuv[3];
472 Standard_Real t = VM2-Vm2;
473 if(t<Adaptor3d_HSurfaceTool::VPeriod(Caro2)) {
474 t=0.5*(Adaptor3d_HSurfaceTool::VPeriod(Caro2)-t);
475 t=(t>KELARG*pasuv[3])? KELARG*pasuv[3] : t;
480 //-- ComputePasInit(pasuv,Um1,UM1,Vm1,VM1,Um2,UM2,Vm2,VM2,Caro1,Caro2);
482 for (Standard_Integer i = 0; i<=3;i++) {
483 pasInit[i] = pasSav[i] = pasuv[i];
486 if(ResoU1>0.0001*pasuv[0]) ResoU1=0.00001*pasuv[0];
487 if(ResoV1>0.0001*pasuv[1]) ResoV1=0.00001*pasuv[1];
488 if(ResoU2>0.0001*pasuv[2]) ResoU2=0.00001*pasuv[2];
489 if(ResoV2>0.0001*pasuv[3]) ResoV2=0.00001*pasuv[3];
491 myStepMin[0] = 100.0*ResoU1;
492 myStepMin[1] = 100.0*ResoV1;
493 myStepMin[2] = 100.0*ResoU2;
494 myStepMin[3] = 100.0*ResoV2;
497 TColStd_Array1OfReal Par(1,4);
505 //==================================================================================
506 // function : PerformFirstPoint
508 //==================================================================================
509 Standard_Boolean IntWalk_PWalking::PerformFirstPoint (const TColStd_Array1OfReal& ParDep,
510 IntSurf_PntOn2S& FirstPoint)
513 close = Standard_False;
516 TColStd_Array1OfReal Param(1,4);
518 for (i=1; i<=4; ++i) {
519 Param(i) = ParDep(i);
521 //-- calculate the first solution point
522 math_FunctionSetRoot Rsnld(myIntersectionOn2S.Function());
524 myIntersectionOn2S.Perform(Param,Rsnld);
525 if (!myIntersectionOn2S.IsDone()) {
526 return Standard_False;
529 if (myIntersectionOn2S.IsEmpty()) {
530 return Standard_False;
533 FirstPoint = myIntersectionOn2S.Point();
534 return Standard_True;
536 //==================================================================================
537 // function : Perform
539 //==================================================================================
540 void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep)
542 Perform(ParDep,Um1,Vm1,Um2,Vm2,UM1,VM1,UM2,VM2);
545 //=======================================================================
546 //function : SQDistPointSurface
547 //purpose : Returns square distance between thePnt and theSurf.
548 // (theU0, theV0) is initial point for extrema
549 //=======================================================================
550 static Standard_Real SQDistPointSurface(const gp_Pnt &thePnt,
551 const Adaptor3d_Surface& theSurf,
552 const Standard_Real theU0,
553 const Standard_Real theV0)
555 Extrema_GenLocateExtPS aExtPS(theSurf);
556 aExtPS.Perform(thePnt, theU0, theV0);
561 return aExtPS.SquareDistance();
564 //==================================================================================
565 // function : IsTangentExtCheck
566 // purpose : Additional check if the surfaces are tangent.
567 // Checks if any point in one surface lie in another surface
568 // (with given tolerance)
569 //==================================================================================
570 static Standard_Boolean IsTangentExtCheck(const Handle(Adaptor3d_HSurface)& theSurf1,
571 const Handle(Adaptor3d_HSurface)& theSurf2,
572 const Standard_Real theU10,
573 const Standard_Real theV10,
574 const Standard_Real theU20,
575 const Standard_Real theV20,
576 const Standard_Real theToler,
577 const Standard_Real theArrStep[])
581 gp_Vec aDu1, aDv1, aDu2, aDv2;
582 theSurf1->D1(theU10, theV10, aPt, aDu1, aDv1);
583 theSurf2->D1(theU20, theV20, aPt, aDu2, aDv2);
585 const gp_Vec aN1(aDu1.Crossed(aDv1)),
586 aN2(aDu2.Crossed(aDv2));
587 const Standard_Real aDP = aN1.Dot(aN2),
588 aSQ1 = aN1.SquareMagnitude(),
589 aSQ2 = aN2.SquareMagnitude();
591 if((aSQ1 < RealSmall()) || (aSQ2 < RealSmall()))
592 return Standard_True; //Tangent
594 if(aDP*aDP < 0.9998*aSQ1*aSQ2)
595 {//cos(ang N1<->N2) < 0.9999
596 return Standard_False; //Not tangent
600 //For two faces (2^2 = 4)
601 const Standard_Real aSQToler = 4.0*theToler*theToler;
602 const Standard_Integer aNbItems = 4;
603 const Standard_Real aParUS1[aNbItems] = { theU10 + theArrStep[0],
604 theU10 - theArrStep[0],
606 const Standard_Real aParVS1[aNbItems] = { theV10, theV10,
607 theV10 + theArrStep[1],
608 theV10 - theArrStep[1]};
609 const Standard_Real aParUS2[aNbItems] = { theU20 + theArrStep[2],
610 theU20 - theArrStep[2],
612 const Standard_Real aParVS2[aNbItems] = { theV20, theV20,
613 theV20 + theArrStep[3],
614 theV20 - theArrStep[3]};
616 for(Standard_Integer i = 0; i < aNbItems; i++)
618 gp_Pnt aP(theSurf1->Value(aParUS1[i], aParVS1[i]));
619 const Standard_Real aSqDist = SQDistPointSurface(aP, theSurf2->Surface(), theU20, theV20);
620 if(aSqDist > aSQToler)
621 return Standard_False;
624 for(Standard_Integer i = 0; i < aNbItems; i++)
626 gp_Pnt aP(theSurf2->Value(aParUS2[i], aParVS2[i]));
627 const Standard_Real aSqDist = SQDistPointSurface(aP, theSurf1->Surface(), theU10, theV10);
628 if(aSqDist > aSQToler)
629 return Standard_False;
632 return Standard_True;
635 //==================================================================================
636 // function : Perform
638 //==================================================================================
639 void IntWalk_PWalking::Perform(const TColStd_Array1OfReal& ParDep,
640 const Standard_Real u1min,
641 const Standard_Real v1min,
642 const Standard_Real u2min,
643 const Standard_Real v2min,
644 const Standard_Real u1max,
645 const Standard_Real v1max,
646 const Standard_Real u2max,
647 const Standard_Real v2max)
649 const Standard_Real aSQDistMax = 1.0e-14;
652 Standard_Integer NbPasOKConseq=0;
653 TColStd_Array1OfReal Param(1,4);
654 IntImp_ConstIsoparametric ChoixIso;
657 done = Standard_False;
660 const Handle(Adaptor3d_HSurface)& Caro1 =myIntersectionOn2S.Function().AuxillarSurface1();
661 const Handle(Adaptor3d_HSurface)& Caro2 =myIntersectionOn2S.Function().AuxillarSurface2();
663 const Standard_Real UFirst1 = Adaptor3d_HSurfaceTool::FirstUParameter(Caro1);
664 const Standard_Real VFirst1 = Adaptor3d_HSurfaceTool::FirstVParameter(Caro1);
665 const Standard_Real ULast1 = Adaptor3d_HSurfaceTool::LastUParameter (Caro1);
666 const Standard_Real VLast1 = Adaptor3d_HSurfaceTool::LastVParameter (Caro1);
668 const Standard_Real UFirst2 = Adaptor3d_HSurfaceTool::FirstUParameter(Caro2);
669 const Standard_Real VFirst2 = Adaptor3d_HSurfaceTool::FirstVParameter(Caro2);
670 const Standard_Real ULast2 = Adaptor3d_HSurfaceTool::LastUParameter (Caro2);
671 const Standard_Real VLast2 = Adaptor3d_HSurfaceTool::LastVParameter (Caro2);
673 ComputePasInit(u1max - u1min,v1max - v1min,u2max - u2min,v2max - v2min);
675 for (Standard_Integer i=0; i<4; ++i)
682 pasInit[i] = pasSav[i] = pasuv[i];
685 line = new IntSurf_LineOn2S ();
687 for (Standard_Integer i=1; i<=4; ++i)
691 //-- reproduce steps uv connected to surfaces Caro1 and Caro2
692 //-- pasuv[] and pasSav[] are modified during the marching
693 for(Standard_Integer i = 0; i < 4; ++i)
695 pasSav[i] = pasuv[i] = pasInit[i];
698 //-- calculate the first solution point
699 math_FunctionSetRoot Rsnld(myIntersectionOn2S.Function());
701 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld);
702 if (!myIntersectionOn2S.IsDone())
708 if (myIntersectionOn2S.IsEmpty())
713 if(myIntersectionOn2S.IsTangent())
718 Standard_Boolean Arrive, DejaReparti;
719 const Standard_Integer RejectIndexMAX = 250000;
720 Standard_Integer IncKey, RejectIndex;
723 DejaReparti = Standard_False;
727 previousPoint = myIntersectionOn2S.Point();
728 previoustg = Standard_False;
729 previousd = myIntersectionOn2S.Direction();
730 previousd1 = myIntersectionOn2S.DirectionOnS1();
731 previousd2 = myIntersectionOn2S.DirectionOnS2();
734 firstd1 = previousd1;
735 firstd2 = previousd2;
736 tgfirst = tglast = Standard_False;
737 choixIsoSav = ChoixIso;
738 //------------------------------------------------------------
739 //-- Test if the first point of marching corresponds
740 //-- to a point on borders.
741 //-- In this case, DejaReparti is initialized as True
743 pf = previousPoint.Value();
744 Standard_Boolean bTestFirstPoint = Standard_True;
746 previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
748 if(IsTangentExtCheck(Caro1, Caro2, Param(1), Param(2), Param(3), Param(4), myTolTang, pasuv))
751 AddAPoint(previousPoint);
753 IntWalk_StatusDeflection aStatus = IntWalk_OK, aPrevStatus = IntWalk_OK;
754 Standard_Boolean NoTestDeflection = Standard_False;
755 Standard_Real SvParam[4], f;
756 Standard_Integer LevelOfEmptyInmyIntersectionOn2S=0;
757 Standard_Integer LevelOfPointConfondu = 0;
758 Standard_Integer LevelOfIterWithoutAppend = -1;
761 const Standard_Real aTol[4] = { Epsilon(UM1 - Um1),
766 Standard_Integer aPrevNbPoints = line->NbPoints();
768 Arrive = Standard_False;
771 aPrevStatus = aStatus;
773 LevelOfIterWithoutAppend++;
774 if(LevelOfIterWithoutAppend>20)
776 Arrive = Standard_True;
780 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
781 LevelOfIterWithoutAppend = 0;
787 case IntImp_UIsoparametricOnCaro1: f = Abs(previousd1.X()); break;
788 case IntImp_VIsoparametricOnCaro1: f = Abs(previousd1.Y()); break;
789 case IntImp_UIsoparametricOnCaro2: f = Abs(previousd2.X()); break;
790 case IntImp_VIsoparametricOnCaro2: f = Abs(previousd2.Y()); break;
798 previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
801 Standard_Real aIncKey, aEps, dP1, dP2, dP3, dP4;
803 dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
804 dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
805 dP3 = sensCheminement * pasuv[2] * previousd2.X() /f;
806 dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
808 aIncKey=5.*(Standard_Real)IncKey;
810 if(ChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < aEps)
815 if(ChoixIso == IntImp_VIsoparametricOnCaro1 && Abs(dP2) < aEps)
820 if(ChoixIso == IntImp_UIsoparametricOnCaro2 && Abs(dP3) < aEps)
825 if(ChoixIso == IntImp_VIsoparametricOnCaro2 && Abs(dP4) < aEps)
835 //==========================
841 Standard_Integer aTryNumber = 0;
842 Standard_Boolean isBadPoint = Standard_False;
843 IntImp_ConstIsoparametric aBestIso = ChoixIso;
846 isBadPoint = Standard_False;
848 ChoixIso= myIntersectionOn2S.Perform(Param, Rsnld, aBestIso);
850 if (myIntersectionOn2S.IsDone() && !myIntersectionOn2S.IsEmpty())
852 //If we go along any surface boundary then it is possible
853 //to find "outboundaried" point.
854 //Nevertheless, if this deflection is quite small, we will be
855 //able to adjust this point to the boundary.
857 Standard_Real aNewPnt[4], anAbsParamDist[4];
858 myIntersectionOn2S.Point().Parameters(aNewPnt[0], aNewPnt[1], aNewPnt[2], aNewPnt[3]);
859 const Standard_Real aParMin[4] = {Um1, Vm1, Um2, Vm2};
860 const Standard_Real aParMax[4] = {UM1, VM1, UM2, VM2};
862 for(Standard_Integer i = 0; i < 4; i++)
864 if(Abs(aNewPnt[i] - aParMin[i]) < aTol[i])
865 aNewPnt[i] = aParMin[i];
866 else if(Abs(aNewPnt[i] - aParMax[i]) < aTol[i])
867 aNewPnt[i] = aParMax[i];
870 if (aNewPnt[0] < Um1 || aNewPnt[0] > UM1 ||
871 aNewPnt[1] < Vm1 || aNewPnt[1] > VM1 ||
872 aNewPnt[2] < Um2 || aNewPnt[2] > UM2 ||
873 aNewPnt[3] < Vm2 || aNewPnt[3] > VM2)
875 // Out of borders, process it later.
879 myIntersectionOn2S.ChangePoint().SetValue(aNewPnt[0],
884 anAbsParamDist[0] = Abs(Param(1) - dP1 - aNewPnt[0]);
885 anAbsParamDist[1] = Abs(Param(2) - dP2 - aNewPnt[1]);
886 anAbsParamDist[2] = Abs(Param(3) - dP3 - aNewPnt[2]);
887 anAbsParamDist[3] = Abs(Param(4) - dP4 - aNewPnt[3]);
888 if (anAbsParamDist[0] < ResoU1 &&
889 anAbsParamDist[1] < ResoV1 &&
890 anAbsParamDist[2] < ResoU2 &&
891 anAbsParamDist[3] < ResoV2 &&
892 aStatus != IntWalk_PasTropGrand)
894 isBadPoint = Standard_True;
895 aBestIso = IntImp_ConstIsoparametric((aBestIso + 1) % 4);
898 } while (isBadPoint && ++aTryNumber <= 4);
900 if (!myIntersectionOn2S.IsDone())
902 //end of line, division
903 Arrive = Standard_False;
908 RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
912 //== Calculation of exact point from Param(.) is possible
913 if (myIntersectionOn2S.IsEmpty())
915 Standard_Real u1,v1,u2,v2;
916 previousPoint.Parameters(u1,v1,u2,v2);
918 Arrive = Standard_False;
919 if(u1<UFirst1 || u1>ULast1)
921 Arrive=Standard_True;
924 if(u2<UFirst2 || u2>ULast2)
926 Arrive=Standard_True;
929 if(v1<VFirst1 || v1>VLast1)
931 Arrive=Standard_True;
934 if(v2<VFirst2 || v2>VLast2)
936 Arrive=Standard_True;
939 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
940 LevelOfEmptyInmyIntersectionOn2S++;
942 if(LevelOfEmptyInmyIntersectionOn2S>10)
952 //============================================================
953 //== A point has been found : T E S T D E F L E C T I O N
954 //============================================================
957 NoTestDeflection = Standard_False;
961 if(--LevelOfEmptyInmyIntersectionOn2S<=0)
963 LevelOfEmptyInmyIntersectionOn2S=0;
964 if(LevelOfIterWithoutAppend < 10)
966 aStatus = TestDeflection(ChoixIso, aStatus);
970 if (aStatus != IntWalk_StepTooSmall)
972 // Bug #0029682 (Boolean intersection with
973 // fuzzy-option hangs).
974 // If aStatus == IntWalk_StepTooSmall then
975 // the counter "LevelOfIterWithoutAppend" will
976 // be nulified in the future if the step is smaller
977 // (see "case IntWalk_StepTooSmall:" below).
978 // Here, we forbid this nulification and thereby provide out from
989 //============================================================
990 //== T r a i t e m e n t s u r S t a t u s ==
991 //============================================================
992 if(LevelOfPointConfondu > 5)
994 aStatus = IntWalk_ArretSurPoint;
995 LevelOfPointConfondu = 0;
998 if(aStatus==IntWalk_OK)
1001 if(NbPasOKConseq >= 5)
1004 Standard_Boolean pastroppetit;
1009 pastroppetit=Standard_True;
1011 if(pasuv[0]<pasInit[0])
1013 t = (pasInit[0]-pasuv[0])*0.25;
1014 if(t>0.1*pasInit[0])
1020 pastroppetit=Standard_False;
1023 if(pasuv[1]<pasInit[1])
1025 t = (pasInit[1]-pasuv[1])*0.25;
1026 if(t>0.1*pasInit[1]) {
1031 pastroppetit=Standard_False;
1034 if(pasuv[2]<pasInit[2])
1036 t = (pasInit[2]-pasuv[2])*0.25;
1037 if(t>0.1*pasInit[2])
1043 pastroppetit=Standard_False;
1046 if(pasuv[3]<pasInit[3])
1048 t = (pasInit[3]-pasuv[3])*0.25;
1049 if(t>0.1*pasInit[3]) {
1053 pastroppetit=Standard_False;
1067 pastroppetit=Standard_False;
1071 while(pastroppetit);
1073 }//aStatus==IntWalk_OK
1078 switch(aStatus)//007
1080 case IntWalk_ArretSurPointPrecedent:
1082 Arrive = Standard_False;
1083 RepartirOuDiviser(DejaReparti, ChoixIso, Arrive);
1086 case IntWalk_PasTropGrand:
1088 Param(1)=SvParam[0];
1089 Param(2)=SvParam[1];
1090 Param(3)=SvParam[2];
1091 Param(4)=SvParam[3];
1093 if(LevelOfIterWithoutAppend > 5)
1095 for (Standard_Integer i = 0; i < 4; i++)
1097 if (pasSav[i] > pasInit[i])
1100 const Standard_Real aDelta = (pasInit[i]-pasSav[i])*0.25;
1102 if(aDelta > Epsilon(pasInit[i]))
1104 pasInit[i] -= aDelta;
1105 if ((aPrevStatus != IntWalk_StepTooSmall) &&
1106 (line->NbPoints() != aPrevNbPoints))
1108 LevelOfIterWithoutAppend = 0;
1111 aPrevNbPoints = line->NbPoints();
1118 case IntWalk_PointConfondu:
1120 LevelOfPointConfondu++;
1122 if(LevelOfPointConfondu>5)
1124 Standard_Boolean pastroppetit;
1128 pastroppetit=Standard_True;
1130 for(Standard_Integer i = 0; i < 4; i++)
1132 if(pasuv[i]<pasInit[i])
1134 pasuv[i]+=(pasInit[i]-pasuv[i])*0.25;
1135 pastroppetit=Standard_False;
1151 pastroppetit=Standard_False;
1155 while(pastroppetit);
1160 case IntWalk_StepTooSmall:
1162 Standard_Boolean hasStepBeenIncreased = Standard_False;
1164 for(Standard_Integer i = 0; i < 4; i++)
1166 const Standard_Real aNewStep = Min(1.5*pasuv[i], pasInit[i]);
1167 if(aNewStep > pasuv[i])
1169 pasuv[i] = aNewStep;
1170 hasStepBeenIncreased = Standard_True;
1174 if(hasStepBeenIncreased)
1176 Param(1)=SvParam[0];
1177 Param(2)=SvParam[1];
1178 Param(3)=SvParam[2];
1179 Param(4)=SvParam[3];
1181 // In order to avoid cyclic changes
1182 // (PasTropGrand --> Decrease step -->
1183 // StepTooSmall --> Increase step --> PasTropGrand...)
1184 // nullify LevelOfIterWithoutAppend only if the condition
1186 if ((aPrevStatus != IntWalk_PasTropGrand) &&
1187 (line->NbPoints() != aPrevNbPoints))
1189 LevelOfIterWithoutAppend = 0;
1192 aPrevNbPoints = line->NbPoints();
1197 Standard_FALLTHROUGH
1199 case IntWalk_ArretSurPoint://006
1201 //=======================================================
1202 //== Stop Test t : Frame on Param(.) ==
1203 //=======================================================
1205 Arrive = TestArret(DejaReparti,Param,ChoixIso);
1206 // JMB 30th December 1999.
1207 // Some statement below should not be put in comment because they are useful.
1208 // See grid CTO 909 A1 which infinitely loops
1209 if(Arrive==Standard_False && aStatus==IntWalk_ArretSurPoint)
1211 Arrive=Standard_True;
1213 std::cout << "IntWalk_PWalking_1.gxx: Problems with intersection"<<std::endl;
1219 NbPasOKConseq = -10;
1224 //=====================================================
1225 //== Param(.) is in the limits ==
1226 //== and does not end a closed line ==
1227 //=====================================================
1228 //== Check on the current point of myInters
1229 Standard_Boolean pointisvalid = Standard_False;
1231 Standard_Real u1,v1,u2,v2;
1232 myIntersectionOn2S.Point().Parameters(u1,v1,u2,v2);
1235 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1236 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1237 v1 >= Vm1 && v2 >= Vm2)
1239 pointisvalid=Standard_True;
1246 previousPoint = myIntersectionOn2S.Point();
1247 previoustg = myIntersectionOn2S.IsTangent();
1251 previousd = myIntersectionOn2S.Direction();
1252 previousd1 = myIntersectionOn2S.DirectionOnS1();
1253 previousd2 = myIntersectionOn2S.DirectionOnS2();
1255 //=====================================================
1256 //== Check on the previous Point
1258 Standard_Real u1,v1,u2,v2;
1259 previousPoint.Parameters(u1,v1,u2,v2);
1260 if( u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1261 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1262 v1 >= Vm1 && v2 >= Vm2)
1264 pl = previousPoint.Value();
1267 if(pf.SquareDistance(pl) < aSQDistMax)
1277 bTestFirstPoint = Standard_False;
1281 AddAPoint(previousPoint);
1284 if(RejectIndex >= RejectIndexMAX)
1286 Arrive = Standard_True;
1291 LevelOfIterWithoutAppend = 0;
1295 //====================================================
1297 if (aStatus == IntWalk_ArretSurPoint)
1299 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1303 if (line->NbPoints() == 2)
1305 pasSav[0] = pasuv[0];
1306 pasSav[1] = pasuv[1];
1307 pasSav[2] = pasuv[2];
1308 pasSav[3] = pasuv[3];
1310 if ((aPrevStatus == IntWalk_PasTropGrand) &&
1311 (LevelOfIterWithoutAppend > 0))
1313 pasInit[0] = pasuv[0];
1314 pasInit[1] = pasuv[1];
1315 pasInit[2] = pasuv[2];
1316 pasInit[3] = pasuv[3];
1325 //================= la ligne est fermee ===============
1326 AddAPoint(line->Value(1)); //ligne fermee
1327 LevelOfIterWithoutAppend=0;
1331 //====================================================
1332 //== Param was not in the limits (was reframed)
1333 //====================================================
1334 Standard_Boolean bPrevNotTangent = !previoustg || !myIntersectionOn2S.IsTangent();
1336 IntImp_ConstIsoparametric SauvChoixIso = ChoixIso;
1337 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld,ChoixIso);
1339 if(!myIntersectionOn2S.IsEmpty()) //002
1341 // mutially outpasses in the square or intersection in corner
1343 if(TestArret(Standard_True,Param,ChoixIso))
1345 NbPasOKConseq = -10;
1346 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld,ChoixIso);
1348 if(!myIntersectionOn2S.IsEmpty())
1350 previousPoint = myIntersectionOn2S.Point();
1351 previoustg = myIntersectionOn2S.IsTangent();
1355 previousd = myIntersectionOn2S.Direction();
1356 previousd1 = myIntersectionOn2S.DirectionOnS1();
1357 previousd2 = myIntersectionOn2S.DirectionOnS2();
1360 pl = previousPoint.Value();
1364 if(pf.SquareDistance(pl) < aSQDistMax)
1374 bTestFirstPoint = Standard_False;
1378 AddAPoint(previousPoint);
1381 if(RejectIndex >= RejectIndexMAX)
1383 Arrive = Standard_True;
1388 LevelOfIterWithoutAppend=0;
1389 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1393 //fail framing divides the step
1394 Arrive = Standard_False;
1395 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1396 NoTestDeflection = Standard_True;
1397 ChoixIso = SauvChoixIso;
1402 // save the last point
1403 // to revert to it if the current point is out of bounds
1405 IntSurf_PntOn2S previousPointSave = previousPoint;
1406 Standard_Boolean previoustgSave = previoustg;
1407 gp_Dir previousdSave = previousd;
1408 gp_Dir2d previousd1Save = previousd1;
1409 gp_Dir2d previousd2Save = previousd2;
1411 previousPoint = myIntersectionOn2S.Point();
1412 previoustg = myIntersectionOn2S.IsTangent();
1413 Arrive = Standard_False;
1417 previousd = myIntersectionOn2S.Direction();
1418 previousd1 = myIntersectionOn2S.DirectionOnS1();
1419 previousd2 = myIntersectionOn2S.DirectionOnS2();
1422 //========================================
1423 //== Check on PreviousPoint @@
1426 Standard_Real u1,v1,u2,v2;
1427 previousPoint.Parameters(u1,v1,u2,v2);
1429 //To save initial 2d points
1430 gp_Pnt2d ParamPntOnS1(Param(1), Param(2));
1431 gp_Pnt2d ParamPntOnS2(Param(3), Param(4));
1433 ///////////////////////////
1441 Standard_Boolean bFlag1, bFlag2;
1442 Standard_Real aTol2D=1.e-11;
1444 bFlag1=u1 >= Um1-aTol2D && v1 >= Vm1-aTol2D && u1 <= UM1+aTol2D && v1 <= VM1+aTol2D;
1445 bFlag2=u2 >= Um2-aTol2D && v2 >= Vm2-aTol2D && u2 <= UM2+aTol2D && v2 <= VM2+aTol2D;
1446 if (bFlag1 && bFlag2)
1448 if (line->NbPoints() > 1)
1450 IntSurf_PntOn2S prevprevPoint = line->Value(line->NbPoints()-1);
1451 Standard_Real ppU1, ppV1, ppU2, ppV2;
1452 prevprevPoint.Parameters(ppU1, ppV1, ppU2, ppV2);
1453 Standard_Real pU1, pV1, pU2, pV2;
1454 previousPointSave.Parameters(pU1, pV1, pU2, pV2);
1455 gp_Vec2d V1onS1(gp_Pnt2d(ppU1, ppV1), gp_Pnt2d(pU1, pV1));
1456 gp_Vec2d V2onS1(gp_Pnt2d(pU1, pV1), gp_Pnt2d(u1, v1));
1457 gp_Vec2d V1onS2(gp_Pnt2d(ppU2, ppV2), gp_Pnt2d(pU2, pV2));
1458 gp_Vec2d V2onS2(gp_Pnt2d(pU2, pV2), gp_Pnt2d(u2, v2));
1460 const Standard_Real aDot1 = V1onS1 * V2onS1;
1461 const Standard_Real aDot2 = V1onS2 * V2onS2;
1463 if ((aDot1 < 0.0) || (aDot2 < 0.0))
1465 Arrive = Standard_True;
1470 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1471 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1472 v1 >= Vm1 && v2 >= Vm2) {
1475 pl = previousPoint.Value();
1479 if(pf.SquareDistance(pl) < aSQDistMax)
1490 bTestFirstPoint = Standard_False;
1494 //To avoid walking around the same point
1495 //in the tangent zone near a border
1499 //There are three consecutive points:
1500 //previousPointSave -> ParamPnt -> curPnt.
1502 Standard_Real prevU1, prevV1, prevU2, prevV2;
1503 previousPointSave.Parameters(prevU1, prevV1, prevU2, prevV2);
1504 gp_Pnt2d prevPntOnS1(prevU1, prevV1), prevPntOnS2(prevU2, prevV2);
1505 gp_Pnt2d curPntOnS1(u1, v1), curPntOnS2(u2, v2);
1506 gp_Vec2d PrevToParamOnS1(prevPntOnS1, ParamPntOnS1);
1507 gp_Vec2d PrevToCurOnS1(prevPntOnS1, curPntOnS1);
1508 gp_Vec2d PrevToParamOnS2(prevPntOnS2, ParamPntOnS2);
1509 gp_Vec2d PrevToCurOnS2(prevPntOnS2, curPntOnS2);
1510 Standard_Real MaxAngle = 3*M_PI/4;
1511 Standard_Real anAngleS1 = 0.0, anAngleS2 = 0.0;
1512 const Standard_Real aSQMParS1 = PrevToParamOnS1.SquareMagnitude();
1513 const Standard_Real aSQMParS2 = PrevToParamOnS2.SquareMagnitude();
1514 const Standard_Real aSQMCurS1 = PrevToCurOnS1.SquareMagnitude();
1515 const Standard_Real aSQMCurS2 = PrevToCurOnS2.SquareMagnitude();
1517 if(aSQMCurS1 < gp::Resolution())
1519 //We came back to the one of previos point.
1520 //Therefore, we must break;
1524 else if(aSQMParS1 < gp::Resolution())
1526 //We are walking along tangent zone.
1527 //It should be continued.
1532 anAngleS1 = Abs(PrevToParamOnS1.Angle(PrevToCurOnS1));
1535 if(aSQMCurS2 < gp::Resolution())
1537 //We came back to the one of previos point.
1538 //Therefore, we must break;
1542 else if(aSQMParS2 < gp::Resolution())
1544 //We are walking along tangent zone.
1545 //It should be continued;
1550 anAngleS2 = Abs(PrevToParamOnS2.Angle(PrevToCurOnS2));
1553 if ((anAngleS1 > MaxAngle) && (anAngleS2 > MaxAngle))
1555 Arrive = Standard_True;
1560 //Check singularity.
1561 //I.e. check if we are walking along direction, which does not
1562 //result in comming to any point (i.e. derivative
1563 //3D-intersection curve along this direction is equal to 0).
1564 //A sphere with direction {dU=1, dV=0} from point
1565 //(U=0, V=M_PI/2) can be considered as example for
1566 //this case (we cannot find another 3D-point if we go thus).
1568 //Direction chosen along 1st and 2nd surface correspondingly
1569 const gp_Vec2d aDirS1(prevPntOnS1, curPntOnS1),
1570 aDirS2(prevPntOnS2, curPntOnS2);
1573 gp_Vec aDuS1, aDvS1, aDuS2, aDvS2;
1575 myIntersectionOn2S.Function().AuxillarSurface1()->
1576 D1(curPntOnS1.X(), curPntOnS1.Y(), aPtemp, aDuS1, aDvS1);
1577 myIntersectionOn2S.Function().AuxillarSurface2()->
1578 D1(curPntOnS2.X(), curPntOnS2.Y(), aPtemp, aDuS2, aDvS2);
1580 //Derivative WLine along (it is vector-function indeed)
1582 //(https://en.wikipedia.org/wiki/Directional_derivative#Variation_using_only_direction_of_vector).
1583 //F1 - on the 1st surface, F2 - on the 2nd surface.
1584 //x, y, z - coordinates of derivative vector.
1585 const Standard_Real aF1x = aDuS1.X()*aDirS1.X() +
1586 aDvS1.X()*aDirS1.Y();
1587 const Standard_Real aF1y = aDuS1.Y()*aDirS1.X() +
1588 aDvS1.Y()*aDirS1.Y();
1589 const Standard_Real aF1z = aDuS1.Z()*aDirS1.X() +
1590 aDvS1.Z()*aDirS1.Y();
1591 const Standard_Real aF2x = aDuS2.X()*aDirS2.X() +
1592 aDvS2.X()*aDirS2.Y();
1593 const Standard_Real aF2y = aDuS2.Y()*aDirS2.X() +
1594 aDvS2.Y()*aDirS2.Y();
1595 const Standard_Real aF2z = aDuS2.Z()*aDirS2.X() +
1596 aDvS2.Z()*aDirS2.Y();
1598 const Standard_Real aF1 = aF1x*aF1x + aF1y*aF1y + aF1z*aF1z;
1599 const Standard_Real aF2 = aF2x*aF2x + aF2y*aF2y + aF2z*aF2z;
1601 if((aF1 < gp::Resolution()) && (aF2 < gp::Resolution()))
1603 //All derivative are equal to 0. Therefore, there is
1604 //no point in going along direction chosen.
1605 Arrive = Standard_True;
1609 }//if (previoustg) cond.
1611 ////////////////////////////////////////
1612 AddAPoint(previousPoint);
1615 if(RejectIndex >= RejectIndexMAX)
1617 Arrive = Standard_True;
1623 LevelOfIterWithoutAppend=0;
1624 Arrive = Standard_True;
1628 // revert to the last correctly calculated point
1629 previousPoint = previousPointSave;
1630 previoustg = previoustgSave;
1631 previousd = previousdSave;
1632 previousd1 = previousd1Save;
1633 previousd2 = previousd2Save;
1638 Standard_Boolean wasExtended = Standard_False;
1640 if(Arrive && myIntersectionOn2S.IsTangent() && bPrevNotTangent)
1642 if(ExtendLineInCommonZone(SauvChoixIso, DejaReparti))
1644 wasExtended = Standard_True;
1645 Arrive = Standard_False;
1646 ChoixIso = SauvChoixIso;
1650 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1653 myIntersectionOn2S.IsDone() && !myIntersectionOn2S.IsEmpty() &&
1654 myIntersectionOn2S.IsTangent() && bPrevNotTangent &&
1657 if(ExtendLineInCommonZone(SauvChoixIso, DejaReparti))
1659 wasExtended = Standard_True;
1660 Arrive = Standard_False;
1661 ChoixIso = SauvChoixIso;
1664 }//else !TestArret() $
1665 }//$$ end successful framing on border (!myIntersectionOn2S.IsEmpty())
1668 //echec framing on border; division of step
1669 Arrive = Standard_False;
1670 NoTestDeflection = Standard_True;
1671 RepartirOuDiviser(DejaReparti,ChoixIso,Arrive);
1673 }//$$$ end framing on border (!close)
1674 }//004 fin TestArret return Arrive = True
1675 } // 006case IntWalk_ArretSurPoint: end Processing Status = OK or ArretSurPoint
1676 } //007 switch(aStatus)
1677 } //008 end processing point (TEST DEFLECTION)
1678 } //009 end processing line (else if myIntersectionOn2S.IsDone())
1679 } //010 end if first departure point allows marching while (!Arrive)
1681 done = Standard_True;
1683 // ===========================================================================================================
1684 // function: ExtendLineInCommonZone
1685 // purpose: Extends already computed line inside tangent zone in the direction given by theChoixIso.
1686 // Returns Standard_True if the line was extended through tangent zone and the last computed point
1687 // is outside the tangent zone (but it is not put into the line). Otherwise returns Standard_False.
1688 // ===========================================================================================================
1689 Standard_Boolean IntWalk_PWalking::ExtendLineInCommonZone(const IntImp_ConstIsoparametric theChoixIso,
1690 const Standard_Boolean theDirectionFlag)
1692 Standard_Boolean bOutOfTangentZone = Standard_False;
1693 Standard_Boolean bStop = !myIntersectionOn2S.IsTangent();
1694 Standard_Integer dIncKey = 1;
1695 TColStd_Array1OfReal Param(1,4);
1696 IntWalk_StatusDeflection aStatus = IntWalk_OK;
1697 Standard_Integer nbIterWithoutAppend = 0;
1698 Standard_Integer nbEqualPoints = 0;
1699 Standard_Integer parit = 0;
1700 Standard_Integer uvit = 0;
1701 IntSurf_SequenceOfPntOn2S aSeqOfNewPoint;
1704 nbIterWithoutAppend++;
1706 if((nbIterWithoutAppend > 20) || (nbEqualPoints > 20)) {
1708 std::cout<<"Infinite loop detected. Stop iterations (IntWalk_PWalking_1.gxx)" << std::endl;
1710 bStop = Standard_True;
1713 Standard_Real f = 0.;
1715 switch (theChoixIso)
1717 case IntImp_UIsoparametricOnCaro1: f = Abs(previousd1.X()); break;
1718 case IntImp_VIsoparametricOnCaro1: f = Abs(previousd1.Y()); break;
1719 case IntImp_UIsoparametricOnCaro2: f = Abs(previousd2.X()); break;
1720 case IntImp_VIsoparametricOnCaro2: f = Abs(previousd2.Y()); break;
1725 previousPoint.Parameters(Param(1),Param(2),Param(3),Param(4));
1727 Standard_Real dP1 = sensCheminement * pasuv[0] * previousd1.X() /f;
1728 Standard_Real dP2 = sensCheminement * pasuv[1] * previousd1.Y() /f;
1729 Standard_Real dP3 = sensCheminement * pasuv[2] * previousd2.X() /f;
1730 Standard_Real dP4 = sensCheminement * pasuv[3] * previousd2.Y() /f;
1732 if(theChoixIso == IntImp_UIsoparametricOnCaro1 && Abs(dP1) < 1.e-7) dP1 *= (5. * (Standard_Real)dIncKey);
1733 if(theChoixIso == IntImp_VIsoparametricOnCaro1 && Abs(dP2) < 1.e-7) dP2 *= (5. * (Standard_Real)dIncKey);
1734 if(theChoixIso == IntImp_UIsoparametricOnCaro2 && Abs(dP3) < 1.e-7) dP3 *= (5. * (Standard_Real)dIncKey);
1735 if(theChoixIso == IntImp_VIsoparametricOnCaro2 && Abs(dP4) < 1.e-7) dP4 *= (5. * (Standard_Real)dIncKey);
1741 Standard_Real SvParam[4];
1742 IntImp_ConstIsoparametric ChoixIso = theChoixIso;
1744 for(parit = 0; parit < 4; parit++) {
1745 SvParam[parit] = Param(parit+1);
1747 math_FunctionSetRoot Rsnld(myIntersectionOn2S.Function());
1748 ChoixIso = myIntersectionOn2S.Perform(Param,Rsnld, theChoixIso);
1750 if (!myIntersectionOn2S.IsDone()) {
1751 return bOutOfTangentZone;
1754 if (myIntersectionOn2S.IsEmpty()) {
1755 return bOutOfTangentZone;
1758 aStatus = TestDeflection(ChoixIso, aStatus);
1760 if(aStatus == IntWalk_OK) {
1762 for(uvit = 0; uvit < 4; uvit++) {
1763 if(pasuv[uvit] < pasInit[uvit]) {
1764 pasuv[uvit] = pasInit[uvit];
1770 case IntWalk_ArretSurPointPrecedent:
1772 bStop = Standard_True;
1773 bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1776 case IntWalk_PasTropGrand:
1778 for(parit = 0; parit < 4; parit++) {
1779 Param(parit+1) = SvParam[parit];
1781 Standard_Boolean bDecrease = Standard_False;
1783 for(uvit = 0; uvit < 4; uvit++) {
1784 if(pasSav[uvit] < pasInit[uvit]) {
1785 pasInit[uvit] -= (pasInit[uvit] - pasSav[uvit]) * 0.1;
1786 bDecrease = Standard_True;
1790 if(bDecrease) nbIterWithoutAppend--;
1793 case IntWalk_PointConfondu:
1795 for(uvit = 0; uvit < 4; uvit++) {
1796 if(pasuv[uvit] < pasInit[uvit]) {
1797 pasuv[uvit] += (pasInit[uvit] - pasuv[uvit]) * 0.1;
1803 case IntWalk_ArretSurPoint:
1806 bStop = TestArret(theDirectionFlag, Param, ChoixIso);
1811 Standard_Real u11,v11,u12,v12;
1812 myIntersectionOn2S.Point().Parameters(u11,v11,u12,v12);
1813 Standard_Real u21,v21,u22,v22;
1814 previousPoint.Parameters(u21,v21,u22,v22);
1816 if(((fabs(u11-u21) < ResoU1) && (fabs(v11-v21) < ResoV1)) ||
1817 ((fabs(u12-u22) < ResoU2) && (fabs(v12-v22) < ResoV2))) {
1826 bStop = bStop || !myIntersectionOn2S.IsTangent();
1827 bOutOfTangentZone = !myIntersectionOn2S.IsTangent();
1830 Standard_Boolean pointisvalid = Standard_False;
1831 Standard_Real u1,v1,u2,v2;
1832 myIntersectionOn2S.Point().Parameters(u1,v1,u2,v2);
1834 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1835 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1836 v1 >= Vm1 && v2 >= Vm2)
1837 pointisvalid = Standard_True;
1840 previousPoint = myIntersectionOn2S.Point();
1841 previoustg = myIntersectionOn2S.IsTangent();
1844 previousd = myIntersectionOn2S.Direction();
1845 previousd1 = myIntersectionOn2S.DirectionOnS1();
1846 previousd2 = myIntersectionOn2S.DirectionOnS2();
1848 Standard_Boolean bAddPoint = Standard_True;
1850 if(line->NbPoints() >= 1) {
1851 gp_Pnt pf = line->Value(1).Value();
1852 gp_Pnt pl = previousPoint.Value();
1854 if(pf.Distance(pl) < Precision::Confusion()) {
1856 if(dIncKey == 5000) return bOutOfTangentZone;
1857 else bAddPoint = Standard_False;
1862 aSeqOfNewPoint.Append(previousPoint);
1863 nbIterWithoutAppend = 0;
1867 if (line->NbPoints() == 2) {
1868 for(uvit = 0; uvit < 4; uvit++) {
1869 pasSav[uvit] = pasuv[uvit];
1873 if ( !pointisvalid ) {
1874 // decrease step if out of bounds
1875 // otherwise the same calculations will be
1876 // repeated several times
1877 if ( ( u1 > UM1 ) || ( u1 < Um1 ) )
1880 if ( ( v1 > VM1 ) || ( v1 < Vm1 ) )
1883 if ( ( u2 > UM2 ) || ( u2 < Um2 ) )
1886 if ( ( v2 > VM2 ) || ( v2 < Vm2 ) )
1891 if(close && (line->NbPoints() >= 1)) {
1893 if(!bOutOfTangentZone) {
1894 aSeqOfNewPoint.Append(line->Value(1)); // line end
1896 nbIterWithoutAppend = 0;
1899 ChoixIso = myIntersectionOn2S.Perform(Param, Rsnld, theChoixIso);
1901 if(myIntersectionOn2S.IsEmpty()) {
1902 bStop = Standard_True;// !myIntersectionOn2S.IsTangent();
1903 bOutOfTangentZone = Standard_False; // !myIntersectionOn2S.IsTangent();
1906 Standard_Boolean bAddPoint = Standard_True;
1907 Standard_Boolean pointisvalid = Standard_False;
1909 previousPoint = myIntersectionOn2S.Point();
1910 Standard_Real u1,v1,u2,v2;
1911 previousPoint.Parameters(u1,v1,u2,v2);
1913 if(u1 <= UM1 && u2 <= UM2 && v1 <= VM1 &&
1914 v2 <= VM2 && u1 >= Um1 && u2 >= Um2 &&
1915 v1 >= Vm1 && v2 >= Vm2)
1916 pointisvalid = Standard_True;
1920 if(line->NbPoints() >= 1) {
1921 gp_Pnt pf = line->Value(1).Value();
1922 gp_Pnt pl = previousPoint.Value();
1924 if(pf.Distance(pl) < Precision::Confusion()) {
1926 if(dIncKey == 5000) return bOutOfTangentZone;
1927 else bAddPoint = Standard_False;
1931 if(bAddPoint && !bOutOfTangentZone) {
1932 aSeqOfNewPoint.Append(previousPoint);
1933 nbIterWithoutAppend = 0;
1948 Standard_Boolean bExtendLine = Standard_False;
1949 Standard_Real u1 = 0., v1 = 0., u2 = 0., v2 = 0.;
1951 Standard_Integer pit = 0;
1953 for(pit = 0; !bExtendLine && (pit < 2); pit++) {
1955 previousPoint.Parameters(u1,v1,u2,v2);
1957 if(aSeqOfNewPoint.Length() > 0)
1958 aSeqOfNewPoint.Value(aSeqOfNewPoint.Length()).Parameters(u1,v1,u2,v2);
1963 if(((u1 - Um1) < ResoU1) ||
1964 ((UM1 - u1) < ResoU1) ||
1965 ((u2 - Um2) < ResoU2) ||
1966 ((UM2 - u2) < ResoU2) ||
1967 ((v1 - Vm1) < ResoV1) ||
1968 ((VM1 - v1) < ResoV1) ||
1969 ((v2 - Vm2) < ResoV2) ||
1970 ((VM2 - v2) < ResoV2))
1971 bExtendLine = Standard_True;
1975 // if(aStatus == IntWalk_OK || aStatus == IntWalk_ArretSurPoint) {
1976 if(aStatus == IntWalk_OK) {
1977 bExtendLine = Standard_True;
1979 if(aSeqOfNewPoint.Length() > 1) {
1980 TColStd_Array1OfReal FirstParams(0, 3), LastParams(0, 3), Resolutions(0, 3);
1981 Resolutions(0) = ResoU1; Resolutions(1) = ResoV1; Resolutions(2) = ResoU2; Resolutions(3) = ResoV2;
1983 aSeqOfNewPoint(1).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
1984 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
1985 aSeqOfNewPoint(aSeqOfNewPoint.Length()).Parameters(LastParams.ChangeValue(0),
1986 LastParams.ChangeValue(1),
1987 LastParams.ChangeValue(2),
1988 LastParams.ChangeValue(3));
1989 Standard_Integer indexofiso = 0;
1991 if(theChoixIso == IntImp_UIsoparametricOnCaro1) indexofiso = 0;
1992 if(theChoixIso == IntImp_VIsoparametricOnCaro1) indexofiso = 1;
1993 if(theChoixIso == IntImp_UIsoparametricOnCaro2) indexofiso = 2;
1994 if(theChoixIso == IntImp_VIsoparametricOnCaro2) indexofiso = 3;
1996 Standard_Integer afirstindex = (indexofiso < 2) ? 0 : 2;
1997 gp_Vec2d aTangentZoneDir(gp_Pnt2d(FirstParams.Value(afirstindex), FirstParams.Value(afirstindex + 1)),
1998 gp_Pnt2d(LastParams.Value(afirstindex), LastParams.Value(afirstindex + 1)));
2000 gp_Dir2d anIsoDir(0, 1);
2002 if((indexofiso == 1) || (indexofiso == 3))
2003 anIsoDir = gp_Dir2d(1, 0);
2005 if(aTangentZoneDir.SquareMagnitude() > gp::Resolution()) {
2006 Standard_Real piquota = M_PI*0.25;
2008 if(fabs(aTangentZoneDir.Angle(anIsoDir)) > piquota) {
2009 Standard_Integer ii = 1, nextii = 2;
2011 Standard_Real asqresol = gp::Resolution();
2012 asqresol *= asqresol;
2015 aSeqOfNewPoint(ii).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
2016 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
2017 aSeqOfNewPoint(ii + 1).Parameters(LastParams.ChangeValue(0), LastParams.ChangeValue(1),
2018 LastParams.ChangeValue(2), LastParams.ChangeValue(3));
2019 d1 = gp_Vec2d(gp_Pnt2d(FirstParams.Value(afirstindex),
2020 FirstParams.Value(afirstindex + 1)),
2021 gp_Pnt2d(LastParams.Value(afirstindex),
2022 LastParams.Value(afirstindex + 1)));
2025 while((d1.SquareMagnitude() < asqresol) &&
2026 (ii < aSeqOfNewPoint.Length()));
2030 while(nextii < aSeqOfNewPoint.Length()) {
2032 gp_Vec2d nextd1(0, 0);
2033 Standard_Integer jj = nextii;
2036 aSeqOfNewPoint(jj).Parameters(FirstParams.ChangeValue(0), FirstParams.ChangeValue(1),
2037 FirstParams.ChangeValue(2), FirstParams.ChangeValue(3));
2038 aSeqOfNewPoint(jj + 1).Parameters(LastParams.ChangeValue(0), LastParams.ChangeValue(1),
2039 LastParams.ChangeValue(2), LastParams.ChangeValue(3));
2040 nextd1 = gp_Vec2d(gp_Pnt2d(FirstParams.Value(afirstindex),
2041 FirstParams.Value(afirstindex + 1)),
2042 gp_Pnt2d(LastParams.Value(afirstindex),
2043 LastParams.Value(afirstindex + 1)));
2047 while((nextd1.SquareMagnitude() < asqresol) &&
2048 (jj < aSeqOfNewPoint.Length()));
2051 if(fabs(d1.Angle(nextd1)) > piquota) {
2052 bExtendLine = Standard_False;
2058 // end if(fabs(aTangentZoneDir.Angle(anIsoDir)
2065 return Standard_False;
2067 Standard_Integer i = 0;
2069 for(i = 1; i <= aSeqOfNewPoint.Length(); i++) {
2070 AddAPoint(aSeqOfNewPoint.Value(i));
2073 return bOutOfTangentZone;
2076 //=======================================================================
2077 //function : DistanceMinimizeByGradient
2081 // theInit should be initialized before function calling.
2082 //=======================================================================
2083 Standard_Boolean IntWalk_PWalking::
2084 DistanceMinimizeByGradient( const Handle(Adaptor3d_HSurface)& theASurf1,
2085 const Handle(Adaptor3d_HSurface)& theASurf2,
2086 TColStd_Array1OfReal& theInit,
2087 const Standard_Real* theStep0)
2089 const Standard_Integer aNbIterMAX = 60;
2090 const Standard_Real aTol = 1.0e-14;
2091 const Standard_Real aTolNul = 1.0 / Precision::Infinite();
2093 // I.e. if theU1 = 0.0 then Epsilon(theU1) = DBL_MIN (~1.0e-308).
2094 // Work with this number is impossible: there is a dangerous to
2095 // obtain Floating-point-overflow. Therefore, we limit this value.
2096 const Standard_Real aMinAddValU1 = Max(Epsilon(theInit(1)), aTolNul);
2097 const Standard_Real aMinAddValV1 = Max(Epsilon(theInit(2)), aTolNul);
2098 const Standard_Real aMinAddValU2 = Max(Epsilon(theInit(3)), aTolNul);
2099 const Standard_Real aMinAddValV2 = Max(Epsilon(theInit(4)), aTolNul);
2101 Handle(Geom_Surface) aS1, aS2;
2103 if (theASurf1->GetType() != GeomAbs_BezierSurface &&
2104 theASurf1->GetType() != GeomAbs_BSplineSurface)
2105 return Standard_True;
2106 if (theASurf2->GetType() != GeomAbs_BezierSurface &&
2107 theASurf2->GetType() != GeomAbs_BSplineSurface)
2108 return Standard_True;
2110 Standard_Boolean aStatus = Standard_False;
2113 gp_Vec aD1u, aD1v, aD2U, aD2V;
2115 theASurf1->D1(theInit(1), theInit(2), aP1, aD1u, aD1v);
2116 theASurf2->D1(theInit(3), theInit(4), aP2, aD2U, aD2V);
2118 Standard_Real aSQDistPrev = aP1.SquareDistance(aP2);
2120 gp_Vec aP12(aP1, aP2);
2122 Standard_Real aGradFu(-aP12.Dot(aD1u));
2123 Standard_Real aGradFv(-aP12.Dot(aD1v));
2124 Standard_Real aGradFU( aP12.Dot(aD2U));
2125 Standard_Real aGradFV( aP12.Dot(aD2V));
2127 Standard_Real aStepU1 = 1.0e-6, aStepV1 = 1.0e-6,
2128 aStepU2 = 1.0e-6, aStepV2 = 1.0e-6;
2132 aStepU1 = theStep0[0];
2133 aStepV1 = theStep0[1];
2134 aStepU2 = theStep0[2];
2135 aStepV2 = theStep0[3];
2138 Standard_Boolean flRepeat = Standard_True;
2139 Standard_Integer aNbIter = aNbIterMAX;
2143 Standard_Real anAdd = aGradFu*aStepU1;
2144 const Standard_Real aPARu = theInit(1) - Sign(Max(Abs(anAdd), aMinAddValU1), anAdd);
2146 anAdd = aGradFv*aStepV1;
2147 const Standard_Real aPARv = theInit(2) - Sign(Max(Abs(anAdd), aMinAddValV1), anAdd);
2149 anAdd = aGradFU*aStepU2;
2150 const Standard_Real aParU = theInit(3) - Sign(Max(Abs(anAdd), aMinAddValU2), anAdd);
2152 anAdd = aGradFV*aStepV2;
2153 const Standard_Real aParV = theInit(4) - Sign(Max(Abs(anAdd), aMinAddValV2), anAdd);
2157 theASurf1->D1(aPARu, aPARv, aPt1, aD1u, aD1v);
2158 theASurf2->D1(aParU, aParV, aPt2, aD2U, aD2V);
2160 Standard_Real aSQDist = aPt1.SquareDistance(aPt2);
2162 if(aSQDist < aSQDistPrev)
2164 aSQDistPrev = aSQDist;
2170 aStatus = aSQDistPrev < aTol;
2180 flRepeat = Standard_False;
2184 theASurf1->D1(theInit(1), theInit(2), aPt1, aD1u, aD1v);
2185 theASurf2->D1(theInit(3), theInit(4), aPt2, aD2U, aD2V);
2187 gp_Vec aPt12(aPt1, aPt2);
2188 aGradFu = -aPt12.Dot(aD1u);
2189 aGradFv = -aPt12.Dot(aD1v);
2190 aGradFU = aPt12.Dot(aD2U);
2191 aGradFV = aPt12.Dot(aD2V);
2195 aStepU1 = theStep0[0];
2196 aStepV1 = theStep0[1];
2197 aStepU2 = theStep0[2];
2198 aStepV2 = theStep0[3];
2202 aStepU1 = aStepV1 = aStepU2 = aStepV2 = 1.0e-6;
2211 //=======================================================================
2212 //function : DistanceMinimizeByExtrema
2216 // theP0, theU0 and theV0 parameters should be initialized
2217 // before the function calling.
2218 //=======================================================================
2219 Standard_Boolean IntWalk_PWalking::
2220 DistanceMinimizeByExtrema(const Handle(Adaptor3d_HSurface)& theASurf,
2221 const gp_Pnt& theP0,
2222 Standard_Real& theU0,
2223 Standard_Real& theV0,
2224 const Standard_Real* theStep0)
2226 const Standard_Real aTol = 1.0e-14;
2228 gp_Vec aD1Su, aD1Sv, aD2Su, aD2Sv, aD2SuvTemp;
2229 Standard_Real aSQDistPrev = RealLast();
2230 Standard_Real aU = theU0, aV = theV0;
2232 const Standard_Real aStep0[2] = { theStep0 ? theStep0[0] : 1.0,
2233 theStep0 ? theStep0[1] : 1.0 };
2235 Standard_Integer aNbIter = 10;
2238 theASurf->D2(aU, aV, aPS, aD1Su, aD1Sv, aD2Su, aD2Sv, aD2SuvTemp);
2240 gp_Vec aVec(theP0, aPS);
2242 Standard_Real aSQDist = aVec.SquareMagnitude();
2244 if(aSQDist >= aSQDistPrev)
2247 aSQDistPrev = aSQDist;
2252 if(aSQDistPrev < aTol)
2256 const Standard_Real aF1 = aD1Su.Dot(aVec), aF2 = aD1Sv.Dot(aVec);
2259 const Standard_Real aDf1u = aD2Su.Dot(aVec) + aD1Su.Dot(aD1Su),
2260 aDf1v = aD2Su.Dot(aD1Sv),
2262 aDf2v = aD2Sv.Dot(aVec) + aD1Sv.Dot(aD1Sv);
2264 const Standard_Real aDet = aDf1u*aDf2v - aDf1v*aDf2u;
2265 aU -= aStep0[0]*(aDf2v*aF1 - aDf1v*aF2) / aDet;
2266 aV += aStep0[1]*(aDf2u*aF1 - aDf1u*aF2) / aDet;
2270 return (aSQDistPrev < aTol);
2273 //=======================================================================
2274 //function : HandleSingleSingularPoint
2276 //=======================================================================
2277 Standard_Boolean IntWalk_PWalking::HandleSingleSingularPoint(const Handle(Adaptor3d_HSurface)& theASurf1,
2278 const Handle(Adaptor3d_HSurface)& theASurf2,
2279 const Standard_Real the3DTol,
2280 TColStd_Array1OfReal &thePnt)
2282 // u1, v1, u2, v2 order is used.
2283 Standard_Real aLowBorder[4] = {theASurf1->FirstUParameter(),
2284 theASurf1->FirstVParameter(),
2285 theASurf2->FirstUParameter(),
2286 theASurf2->FirstVParameter()};
2287 Standard_Real aUppBorder[4] = {theASurf1->LastUParameter(),
2288 theASurf1->LastVParameter(),
2289 theASurf2->LastUParameter(),
2290 theASurf2->LastVParameter()};
2291 IntImp_ConstIsoparametric aLockedDir[4] = {IntImp_UIsoparametricOnCaro1,
2292 IntImp_VIsoparametricOnCaro1,
2293 IntImp_UIsoparametricOnCaro2,
2294 IntImp_VIsoparametricOnCaro2};
2296 // Create new intersector with new tolerance.
2297 IntWalk_TheInt2S anInt(theASurf1, theASurf2, the3DTol);
2298 math_FunctionSetRoot aRsnld(anInt.Function());
2300 for (Standard_Integer i = 1; i <= 4; ++i)
2302 if ( Abs(thePnt(i) - aLowBorder[i - 1]) < Precision::PConfusion() ||
2303 Abs(thePnt(i) - aUppBorder[i - 1]) < Precision::PConfusion())
2306 anInt.Perform(thePnt,aRsnld, aLockedDir[i - 1]);
2308 if (!anInt.IsDone())
2311 if (anInt.IsEmpty())
2314 anInt.Point().Parameters(thePnt(1), thePnt(2), thePnt(3), thePnt(4));
2316 Standard_Boolean isInDomain = Standard_True;
2317 for (Standard_Integer j = 1; isInDomain && (j <= 4); ++j)
2319 if ((thePnt(j) - aLowBorder[j - 1] + Precision::PConfusion())*
2320 (thePnt(j) - aUppBorder[j - 1] - Precision::PConfusion()) > 0.0)
2322 isInDomain = Standard_False;
2327 return Standard_True;
2331 return Standard_False;
2334 //=======================================================================
2335 //function : SeekPointOnBoundary
2337 //=======================================================================
2338 Standard_Boolean IntWalk_PWalking::
2339 SeekPointOnBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
2340 const Handle(Adaptor3d_HSurface)& theASurf2,
2341 const Standard_Real theU1,
2342 const Standard_Real theV1,
2343 const Standard_Real theU2,
2344 const Standard_Real theV2,
2345 const Standard_Boolean isTheFirst)
2347 Standard_Boolean isOK = Standard_False;
2349 // u1, v1, u2, v2 order is used.
2350 const Standard_Real aLowBorder[4] = {theASurf1->FirstUParameter(),
2351 theASurf1->FirstVParameter(),
2352 theASurf2->FirstUParameter(),
2353 theASurf2->FirstVParameter()};
2354 const Standard_Real aUppBorder[4] = {theASurf1->LastUParameter(),
2355 theASurf1->LastVParameter(),
2356 theASurf2->LastUParameter(),
2357 theASurf2->LastVParameter()};
2359 // Tune solution tolerance according with object size.
2360 const Standard_Real aRes1 = Max(Precision::PConfusion() / theASurf1->UResolution(1.0),
2361 Precision::PConfusion() / theASurf1->VResolution(1.0));
2362 const Standard_Real aRes2 = Max(Precision::PConfusion() / theASurf2->UResolution(1.0),
2363 Precision::PConfusion() / theASurf2->VResolution(1.0));
2364 const Standard_Real a3DTol = Max(aRes1, aRes2);
2365 const Standard_Real aTol = Max(Precision::Confusion(), a3DTol);
2367 // u1, v1, u2, v2 order is used.
2368 TColStd_Array1OfReal aPnt(1,4);
2369 aPnt(1) = theU1; aPnt(2) = theV1; aPnt(3) = theU2; aPnt(4) = theV2;
2370 TColStd_Array1OfReal aSingularPnt(aPnt);
2372 Standard_Integer aNbIter = 20;
2373 Standard_Boolean aStatus = Standard_False;
2377 aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, aPnt);
2378 if (aStatus && !AdjustToDomain(4, &aPnt(1), &aLowBorder[0], &aUppBorder[0]))
2381 aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(aPnt(3), aPnt(4)),
2383 if (aStatus && !AdjustToDomain(2, &aPnt(1), &aLowBorder[0], &aUppBorder[0]))
2386 aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(aPnt(1), aPnt(2)),
2388 if (aStatus && !AdjustToDomain(2, &aPnt(3), &aLowBorder[2], &aUppBorder[2]))
2391 while(!aStatus && (aNbIter > 0));
2393 // Handle singular points.
2394 Standard_Boolean aSingularStatus = HandleSingleSingularPoint(theASurf1,
2398 if (aSingularStatus)
2399 aPnt = aSingularPnt;
2401 if (!aStatus && !aSingularStatus)
2406 gp_Pnt aP1 = theASurf1->Value(aPnt(1), aPnt(2));
2407 gp_Pnt aP2 = theASurf2->Value(aPnt(3), aPnt(4));
2408 const gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2410 const Standard_Real aSQDist = aPInt.SquareDistance(aP1);
2411 if (aSQDist > aTol * aTol)
2416 //Found point is true intersection point
2417 IntSurf_PntOn2S anIP;
2418 anIP.SetValue(aPInt, aPnt(1), aPnt(2), aPnt(3), aPnt(4));
2420 //The main idea of checks below is to define if insertion of
2421 //addition point (on the boundary) does not lead to invalid
2422 //intersection curve (e.g. having a loop).
2424 //Loops are detected with rotation angle of the Walking-line (WL).
2425 //If there is hairpin bend then insertion is forbidden.
2427 //There are at least two possible problems:
2428 // 1. There are some cases when two neighbor points of the WL
2429 // are almost coincident (the distance between them is less
2430 // than Precision::Confusion). It is impossible to define
2431 // rotation angle in these cases. Therefore, points with
2432 // "good" distances should be selected.
2434 // 2. Intersection point on the surface boundary has highest
2435 // priority in compare with other "middle" points. Therefore,
2436 // if insertion of new point will result in a bend then some
2437 // "middle" points should be deleted in order to provide
2438 // correct insertion.
2440 //Problem test cases:
2441 // test bugs modalg_5 bug24585_1
2442 // test boolean bcut_complex G7
2443 // test bugs moddata_2 bug469
2447 while (line->NbPoints() > 1)
2449 const Standard_Integer aNbPnts = line->NbPoints();
2451 Standard_Integer aPInd = 1;
2452 for (; aPInd <= aNbPnts; aPInd++)
2454 aP1.SetXYZ(line->Value(aPInd).Value().XYZ());
2455 if (aP1.SquareDistance(aPInt) > Precision::SquareConfusion())
2459 else if (aPInd == 1)
2461 // After insertion, we will obtain
2462 // two coincident points in the line.
2463 // Therefore, insertion is forbidden.
2468 for (++aPInd; aPInd <= aNbPnts; aPInd++)
2470 aP2.SetXYZ(line->Value(aPInd).Value().XYZ());
2471 if (aP1.SquareDistance(aP2) > Precision::SquareConfusion())
2475 if (aPInd > aNbPnts)
2480 const gp_XYZ aDir01(aP1.XYZ() - aPInt.XYZ());
2481 const gp_XYZ aDir12(aP2.XYZ() - aP1.XYZ());
2483 if (aDir01.Dot(aDir12) > 0.0)
2491 line->InsertBefore(1, anIP);
2492 isOK = Standard_True;
2496 while (line->NbPoints() > 1)
2498 const Standard_Integer aNbPnts = line->NbPoints();
2500 gp_Pnt aPPrev, aPCurr;
2501 Standard_Integer aPInd = aNbPnts;
2502 for (; aPInd > 0; aPInd--)
2504 aPCurr.SetXYZ(line->Value(aPInd).Value().XYZ());
2505 if (aPCurr.SquareDistance(aPInt) > Precision::SquareConfusion())
2509 else if (aPInd == aNbPnts)
2511 // After insertion, we will obtain
2512 // two coincident points in the line.
2513 // Therefore, insertion is forbidden.
2518 for (--aPInd; aPInd > 0; aPInd--)
2520 aPPrev.SetXYZ(line->Value(aPInd).Value().XYZ());
2521 if (aPCurr.SquareDistance(aPPrev) > Precision::SquareConfusion())
2530 const gp_XYZ aDirPC(aPCurr.XYZ() - aPPrev.XYZ());
2531 const gp_XYZ aDirCN(aPInt.XYZ() - aPCurr.XYZ());
2533 if (aDirPC.Dot(aDirCN) > 0.0)
2538 RemoveAPoint(aNbPnts);
2542 isOK = Standard_True;
2548 //=======================================================================
2549 //function : PutToBoundary
2551 //=======================================================================
2552 Standard_Boolean IntWalk_PWalking::
2553 PutToBoundary(const Handle(Adaptor3d_HSurface)& theASurf1,
2554 const Handle(Adaptor3d_HSurface)& theASurf2)
2556 const Standard_Real aTolMin = Precision::Confusion();
2558 Standard_Boolean hasBeenAdded = Standard_False;
2560 const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
2561 const Standard_Real aU1bLast = theASurf1->LastUParameter();
2562 const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
2563 const Standard_Real aU2bLast = theASurf2->LastUParameter();
2564 const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
2565 const Standard_Real aV1bLast = theASurf1->LastVParameter();
2566 const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
2567 const Standard_Real aV2bLast = theASurf2->LastVParameter();
2569 Standard_Real aTol = 1.0;
2570 aTol = Min(aTol, aU1bLast - aU1bFirst);
2571 aTol = Min(aTol, aU2bLast - aU2bFirst);
2572 aTol = Min(aTol, aV1bLast - aV1bFirst);
2573 aTol = Min(aTol, aV2bLast - aV2bFirst)*1.0e-3;
2575 if(aTol <= 2.0*aTolMin)
2576 return hasBeenAdded;
2578 Standard_Boolean isNeedAdding = Standard_False;
2579 Standard_Boolean isU1parallel = Standard_False, isV1parallel = Standard_False;
2580 Standard_Boolean isU2parallel = Standard_False, isV2parallel = Standard_False;
2581 IsParallel(line, Standard_True, aTol, isU1parallel, isV1parallel);
2582 IsParallel(line, Standard_False, aTol, isU2parallel, isV2parallel);
2584 Standard_Real u1, v1, u2, v2;
2585 line->Value(1).Parameters(u1, v1, u2, v2);
2586 Standard_Real aDelta = 0.0;
2590 aDelta = u1 - aU1bFirst;
2591 if((aTolMin < aDelta) && (aDelta < aTol))
2594 isNeedAdding = Standard_True;
2598 aDelta = aU1bLast - u1;
2599 if((aTolMin < aDelta) && (aDelta < aTol))
2602 isNeedAdding = Standard_True;
2609 aDelta = u2 - aU2bFirst;
2610 if((aTolMin < aDelta) && (aDelta < aTol))
2613 isNeedAdding = Standard_True;
2617 aDelta = aU2bLast - u2;
2618 if((aTolMin < aDelta) && (aDelta < aTol))
2621 isNeedAdding = Standard_True;
2628 aDelta = v1 - aV1bFirst;
2629 if((aTolMin < aDelta) && (aDelta < aTol))
2632 isNeedAdding = Standard_True;
2636 aDelta = aV1bLast - v1;
2637 if((aTolMin < aDelta) && (aDelta < aTol))
2640 isNeedAdding = Standard_True;
2647 aDelta = v2 - aV2bFirst;
2648 if((aTolMin < aDelta) && (aDelta < aTol))
2651 isNeedAdding = Standard_True;
2655 aDelta = aV2bLast - v2;
2656 if((aTolMin < aDelta) && (aDelta < aTol))
2659 isNeedAdding = Standard_True;
2667 SeekPointOnBoundary(theASurf1, theASurf2, u1,
2668 v1, u2, v2, Standard_True);
2671 const Standard_Integer aNbPnts = line->NbPoints();
2672 isNeedAdding = Standard_False;
2673 line->Value(aNbPnts).Parameters(u1, v1, u2, v2);
2677 aDelta = u1 - aU1bFirst;
2678 if((aTolMin < aDelta) && (aDelta < aTol))
2681 isNeedAdding = Standard_True;
2685 aDelta = aU1bLast - u1;
2686 if((aTolMin < aDelta) && (aDelta < aTol))
2689 isNeedAdding = Standard_True;
2696 aDelta = u2 - aU2bFirst;
2697 if((aTolMin < aDelta) && (aDelta < aTol))
2700 isNeedAdding = Standard_True;
2704 aDelta = aU2bLast - u2;
2705 if((aTolMin < aDelta) && (aDelta < aTol))
2708 isNeedAdding = Standard_True;
2715 aDelta = v1 - aV1bFirst;
2716 if((aTolMin < aDelta) && (aDelta < aTol))
2719 isNeedAdding = Standard_True;
2723 aDelta = aV1bLast - v1;
2724 if((aTolMin < aDelta) && (aDelta < aTol))
2727 isNeedAdding = Standard_True;
2734 aDelta = v2 - aV2bFirst;
2735 if((aTolMin < aDelta) && (aDelta < aTol))
2738 isNeedAdding = Standard_True;
2742 aDelta = aV2bLast - v2;
2743 if((aTolMin < aDelta) && (aDelta < aTol))
2746 isNeedAdding = Standard_True;
2754 SeekPointOnBoundary(theASurf1, theASurf2, u1,
2755 v1, u2, v2, Standard_False);
2758 return hasBeenAdded;
2761 //=======================================================================
2762 //function : SeekAdditionalPoints
2764 //=======================================================================
2765 Standard_Boolean IntWalk_PWalking::
2766 SeekAdditionalPoints( const Handle(Adaptor3d_HSurface)& theASurf1,
2767 const Handle(Adaptor3d_HSurface)& theASurf2,
2768 const Standard_Integer theMinNbPoints)
2770 const Standard_Real aTol = 1.0e-14;
2771 Standard_Integer aNbPoints = line->NbPoints();
2772 if(aNbPoints > theMinNbPoints)
2773 return Standard_True;
2775 const Standard_Real aU1bFirst = theASurf1->FirstUParameter();
2776 const Standard_Real aU1bLast = theASurf1->LastUParameter();
2777 const Standard_Real aU2bFirst = theASurf2->FirstUParameter();
2778 const Standard_Real aU2bLast = theASurf2->LastUParameter();
2779 const Standard_Real aV1bFirst = theASurf1->FirstVParameter();
2780 const Standard_Real aV1bLast = theASurf1->LastVParameter();
2781 const Standard_Real aV2bFirst = theASurf2->FirstVParameter();
2782 const Standard_Real aV2bLast = theASurf2->LastVParameter();
2785 Standard_Boolean isPrecise = Standard_False;
2787 TColStd_Array1OfReal aPnt(1, 4);
2790 Standard_Integer aNbPointsPrev = 0;
2791 while(aNbPoints < theMinNbPoints && (aNbPoints != aNbPointsPrev))
2793 aNbPointsPrev = aNbPoints;
2794 for(Standard_Integer fp = 1, lp = 2; fp < aNbPoints; fp = lp + 1)
2796 Standard_Real U1f, V1f, U2f, V2f; //first point in 1st and 2nd surafaces
2797 Standard_Real U1l, V1l, U2l, V2l; //last point in 1st and 2nd surafaces
2800 line->Value(fp).Parameters(U1f, V1f, U2f, V2f);
2801 line->Value(lp).Parameters(U1l, V1l, U2l, V2l);
2803 aPnt(1) = 0.5*(U1f + U1l);
2804 if(aPnt(1) < aU1bFirst)
2805 aPnt(1) = aU1bFirst;
2806 if(aPnt(1) > aU1bLast)
2809 aPnt(2) = 0.5*(V1f+V1l);
2810 if(aPnt(2) < aV1bFirst)
2811 aPnt(2) = aV1bFirst;
2812 if(aPnt(2) > aV1bLast)
2815 aPnt(3) = 0.5*(U2f+U2l);
2816 if(aPnt(3) < aU2bFirst)
2817 aPnt(3) = aU2bFirst;
2818 if(aPnt(3) > aU2bLast)
2821 aPnt(4) = 0.5*(V2f+V2l);
2822 if(aPnt(4) < aV2bFirst)
2823 aPnt(4) = aV2bFirst;
2824 if(aPnt(4) > aV2bLast)
2827 Standard_Boolean aStatus = Standard_False;
2828 Standard_Integer aNbIter = 5;
2831 aStatus = DistanceMinimizeByGradient(theASurf1, theASurf2, aPnt);
2837 aStatus = DistanceMinimizeByExtrema(theASurf1, theASurf2->Value(aPnt(3), aPnt(4)), aPnt(1), aPnt(2));
2843 aStatus = DistanceMinimizeByExtrema(theASurf2, theASurf1->Value(aPnt(1), aPnt(2)), aPnt(3), aPnt(4));
2849 while(!aStatus && (--aNbIter > 0));
2853 gp_Pnt aP1 = theASurf1->Value(aPnt(1), aPnt(2)),
2854 aP2 = theASurf2->Value(aPnt(3), aPnt(4));
2855 gp_Pnt aPInt(0.5*(aP1.XYZ() + aP2.XYZ()));
2857 const Standard_Real aSQDist1 = aPInt.SquareDistance(aP1),
2858 aSQDist2 = aPInt.SquareDistance(aP2);
2860 if((aSQDist1 < aTol) && (aSQDist2 < aTol))
2862 IntSurf_PntOn2S anIP;
2863 anIP.SetValue(aPInt, aPnt(1), aPnt(2), aPnt(3), aPnt(4));
2864 line->InsertBefore(lp, anIP);
2866 isPrecise = Standard_True;
2868 if(++aNbPoints >= theMinNbPoints)
2882 void IntWalk_PWalking::
2883 RepartirOuDiviser(Standard_Boolean& DejaReparti,
2884 IntImp_ConstIsoparametric& ChoixIso,
2885 Standard_Boolean& Arrive)
2887 // at the neighborhood of a point, there is a fail of marching
2888 // it is required to divide the steps to try to continue
2889 // if the step is too small if we are on border
2890 // restart in another direction if it was not done, otherwise stop
2893 // Standard_Integer i;
2894 if (Arrive) { //restart in the other direction
2895 if (!DejaReparti ) {
2896 Arrive = Standard_False;
2897 DejaReparti = Standard_True;
2898 previousPoint = line->Value(1);
2899 previoustg = Standard_False;
2900 previousd1 = firstd1;
2901 previousd2 = firstd2;
2903 myTangentIdx = line->NbPoints();
2907 //-- printf("\nIntWalk_PWalking_2.gxx Reverse %3d\n",indextg);
2908 sensCheminement = -1;
2910 tglast = Standard_False;
2911 ChoixIso = choixIsoSav;
2918 Standard_Real u1,v1,u2,v2;
2919 Standard_Real U1,V1,U2,V2;
2920 Standard_Integer nn=line->NbPoints();
2922 line->Value(nn).Parameters(u1,v1,u2,v2);
2923 line->Value(nn-1).Parameters(U1,V1,U2,V2);
2924 pasuv[0]=Abs(u1-U1);
2925 pasuv[1]=Abs(v1-V1);
2926 pasuv[2]=Abs(u2-U2);
2927 pasuv[3]=Abs(v2-V2);
2934 if ( pasuv[0]*0.5 < ResoU1
2935 && pasuv[1]*0.5 < ResoV1
2936 && pasuv[2]*0.5 < ResoU2
2937 && pasuv[3]*0.5 < ResoV2
2940 tglast = Standard_True; // IS IT ENOUGH ????
2944 { //restart in the other direction
2945 DejaReparti = Standard_True;
2946 previousPoint = line->Value(1);
2947 previoustg = Standard_False;
2948 previousd1 = firstd1;
2949 previousd2 = firstd2;
2951 myTangentIdx = line->NbPoints();
2955 //-- printf("\nIntWalk_PWalking_2.gxx Reverse %3d\n",indextg);
2957 sensCheminement = -1;
2959 tglast = Standard_False;
2960 ChoixIso = choixIsoSav;
2968 Standard_Real u1,v1,u2,v2;
2969 Standard_Real U1,V1,U2,V2;
2970 Standard_Integer nn=line->NbPoints();
2972 line->Value(nn).Parameters(u1,v1,u2,v2);
2973 line->Value(nn-1).Parameters(U1,V1,U2,V2);
2974 pasuv[0]=Abs(u1-U1);
2975 pasuv[1]=Abs(v1-V1);
2976 pasuv[2]=Abs(u2-U2);
2977 pasuv[3]=Abs(v2-V2);
2981 else Arrive = Standard_True;
2993 //OCC431(apo): modified ->
2994 static const Standard_Real CosRef2D = Cos(M_PI/9.0), AngRef2D = M_PI/2.0;
2996 static const Standard_Real d = 7.0;
2999 IntWalk_StatusDeflection IntWalk_PWalking::TestDeflection(const IntImp_ConstIsoparametric choixIso,
3000 const IntWalk_StatusDeflection theStatus)
3002 // test if vector is observed by calculating an increase of vector
3003 // or the previous point and its tangent, the new calculated point and its
3004 // tangent; it is possible to find a cube passing by the 2 points and having as a
3005 // derivative the tangents of the intersection
3006 // calculate the point with parameter 0.5 on cube=p1
3007 // calculate the medium point of 2 points of intersection=p2
3008 // if arrow/2<=||p1p2||<= arrow consider that the vector is observed
3009 // otherwise adjust the step depending on the ratio ||p1p2||/vector
3010 // and the previous step
3011 // test if in 2 tangent planes of surfaces there is no too great angle2d
3012 // grand : if yes divide the step
3013 // test if there is no change of side
3016 if(line->NbPoints() ==1 ) {
3017 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND=STATIC_PRECEDENT_INFLEXION=0;
3020 IntWalk_StatusDeflection aStatus = IntWalk_OK;
3021 Standard_Real FlecheCourante , Ratio = 1.0;
3024 const Handle(Adaptor3d_HSurface)& Caro1 = myIntersectionOn2S.Function().AuxillarSurface1();
3025 const Handle(Adaptor3d_HSurface)& Caro2 = myIntersectionOn2S.Function().AuxillarSurface2();
3027 const IntSurf_PntOn2S& CurrentPoint = myIntersectionOn2S.Point();
3028 //==================================================================================
3029 //========= S t o p o n p o i n t ============
3030 //==================================================================================
3031 if (myIntersectionOn2S.IsTangent()) {
3032 return IntWalk_ArretSurPoint;
3035 const gp_Dir& TgCourante = myIntersectionOn2S.Direction();
3037 const Standard_Real aCosBetweenTangent = TgCourante.Dot(previousd);
3039 //==================================================================================
3040 //========= R i s k o f i n f l e x i o n p o i n t ============
3041 //==================================================================================
3042 if (aCosBetweenTangent < 0) {
3043 //------------------------------------------------------------
3044 //-- Risk of inflexion point : Divide the step by 2
3045 //-- Initialize STATIC_PRECEDENT_INFLEXION so that
3046 //-- at the next call to return Pas_OK if there is no
3047 //-- more risk of the point of inflexion
3048 //------------------------------------------------------------
3054 STATIC_PRECEDENT_INFLEXION+=3;
3055 if (pasuv[0] < ResoU1 && pasuv[1] <ResoV1 && pasuv[2] <ResoU2 && pasuv[3] < ResoV2)
3056 return IntWalk_ArretSurPointPrecedent;
3058 return IntWalk_PasTropGrand;
3061 if(STATIC_PRECEDENT_INFLEXION > 0) {
3062 STATIC_PRECEDENT_INFLEXION -- ;
3067 //==================================================================================
3068 //========= D e t e c t c o n f u s e d P o in t s ===========
3069 //==================================================================================
3071 const Standard_Real aSqDist = previousPoint.Value().
3072 SquareDistance(CurrentPoint.Value());
3075 if (aSqDist < Precision::SquareConfusion()) {
3076 pasInit[0] = Max(pasInit[0], 5.0*ResoU1);
3077 pasInit[1] = Max(pasInit[1], 5.0*ResoV1);
3078 pasInit[2] = Max(pasInit[2], 5.0*ResoU2);
3079 pasInit[3] = Max(pasInit[3], 5.0*ResoV2);
3081 for(Standard_Integer i = 0; i < 4; i++)
3083 pasuv[i] = Max(pasuv[i], Min(1.5*pasuv[i], pasInit[i]));
3085 //Compute local resolution: for OCC26717
3086 if (Abs(pasuv[choixIso] - pasInit[choixIso]) <= Precision::Confusion())
3088 Standard_Real CurU, CurV;
3089 if (choixIso == IntImp_UIsoparametricOnCaro1 ||
3090 choixIso == IntImp_VIsoparametricOnCaro1)
3091 previousPoint.ParametersOnS1(CurU, CurV);
3093 previousPoint.ParametersOnS2(CurU, CurV);
3094 gp_Pnt CurPnt = (choixIso == IntImp_UIsoparametricOnCaro1 ||
3095 choixIso == IntImp_VIsoparametricOnCaro1)?
3096 Adaptor3d_HSurfaceTool::Value(Caro1, CurU, CurV) :
3097 Adaptor3d_HSurfaceTool::Value(Caro2, CurU, CurV);
3101 case IntImp_UIsoparametricOnCaro1:
3103 Adaptor3d_HSurfaceTool::Value(Caro1,
3104 CurU + sensCheminement*pasuv[0],
3107 case IntImp_VIsoparametricOnCaro1:
3109 Adaptor3d_HSurfaceTool::Value(Caro1,
3111 CurV + sensCheminement*pasuv[1]);
3113 case IntImp_UIsoparametricOnCaro2:
3115 Adaptor3d_HSurfaceTool::Value(Caro2,
3116 CurU + sensCheminement*pasuv[2],
3119 case IntImp_VIsoparametricOnCaro2:
3121 Adaptor3d_HSurfaceTool::Value(Caro2,
3123 CurV + sensCheminement*pasuv[3]);
3127 Standard_Real RefDist = CurPnt.Distance(OffsetPnt);
3128 Standard_Real LocalResol = 0.;
3129 if (RefDist > gp::Resolution())
3130 LocalResol = pasuv[choixIso] * tolconf / RefDist;
3131 if (pasuv[choixIso] < 2*LocalResol)
3132 pasuv[choixIso] = pasInit[choixIso] = 2*LocalResol;
3134 ////////////////////////////////////////
3135 aStatus = IntWalk_PointConfondu;
3138 //==================================================================================
3139 Standard_Real Up1,Vp1,Uc1,Vc1,Du1,Dv1,AbsDu1,AbsDu2,AbsDv1,AbsDv2;
3140 Standard_Real Up2,Vp2,Uc2,Vc2,Du2,Dv2;
3142 previousPoint.Parameters(Up1,Vp1,Up2,Vp2);
3143 CurrentPoint.Parameters(Uc1,Vc1,Uc2,Vc2);
3145 Du1 = Uc1 - Up1; Dv1 = Vc1 - Vp1;
3146 Du2 = Uc2 - Up2; Dv2 = Vc2 - Vp2;
3152 //=================================================================================
3153 //==== S t e p o f p r o g r e s s i o n (between previous and Current) =======
3154 //=================================================================================
3155 if ( AbsDu1 < ResoU1 && AbsDv1 < ResoV1
3156 && AbsDu2 < ResoU2 && AbsDv2 < ResoV2) {
3157 pasuv[0] = ResoU1; pasuv[1] = ResoV1; pasuv[2] = ResoU2; pasuv[3] = ResoV2;
3158 return(IntWalk_ArretSurPointPrecedent);
3160 //==================================================================================
3162 Standard_Real tolArea = 100.0;
3163 if (ResoU1 < Precision::PConfusion() ||
3164 ResoV1 < Precision::PConfusion() ||
3165 ResoU2 < Precision::PConfusion() ||
3166 ResoV2 < Precision::PConfusion() )
3167 tolArea = tolArea*2.0;
3169 Standard_Real Cosi1, CosRef1, Ang1, AngRef1, ResoUV1, Duv1, d1, tolCoeff1;
3170 Standard_Real Cosi2, CosRef2, Ang2, AngRef2, ResoUV2, Duv2, d2, tolCoeff2;
3171 Cosi1 = Du1*previousd1.X() + Dv1*previousd1.Y();
3172 Cosi2 = Du2*previousd2.X() + Dv2*previousd2.Y();
3173 Duv1 = Du1*Du1 + Dv1*Dv1;
3174 Duv2 = Du2*Du2 + Dv2*Dv2;
3175 ResoUV1 = ResoU1*ResoU1 + ResoV1*ResoV1;
3176 ResoUV2 = ResoU2*ResoU2 + ResoV2*ResoV2;
3178 //modified by NIZNHY-PKV Wed Nov 13 12:25:44 2002 f
3180 Standard_Real aMinDiv2=Precision::Confusion();
3181 aMinDiv2=aMinDiv2*aMinDiv2;
3184 if (Duv1>aMinDiv2) {
3185 d1 = Abs(ResoUV1/Duv1);
3186 d1 = Min(Sqrt(d1)*tolArea, d);
3188 //d1 = Abs(ResoUV1/Duv1);
3189 //d1 = Min(Sqrt(d1)*tolArea,d);
3190 //modified by NIZNHY-PKV Wed Nov 13 12:34:30 2002 t
3191 tolCoeff1 = Exp(d1);
3193 //modified by NIZNHY-PKV Wed Nov 13 12:34:43 2002 f
3195 if (Duv2>aMinDiv2) {
3196 d2 = Abs(ResoUV2/Duv2);
3197 d2 = Min(Sqrt(d2)*tolArea,d);
3199 //d2 = Abs(ResoUV2/Duv2);
3200 //d2 = Min(Sqrt(d2)*tolArea,d);
3201 //modified by NIZNHY-PKV Wed Nov 13 12:34:53 2002 t
3202 tolCoeff2 = Exp(d2);
3203 CosRef1 = CosRef2D/tolCoeff1;
3204 CosRef2 = CosRef2D/tolCoeff2;
3206 //==================================================================================
3207 //== The points are not confused : ==
3208 //== D e t e c t t h e S t o p a t p r e v i o u s p o i n t ==
3209 //== N o t T o o G r e a t (angle in space UV) ==
3210 //== C h a n g e o f s i d e ==
3211 //==================================================================================
3212 if (aStatus != IntWalk_PointConfondu) {
3213 if(Cosi1*Cosi1 < CosRef1*Duv1 || Cosi2*Cosi2 < CosRef2*Duv2) {
3214 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
3215 if (pasuv[0]<ResoU1 && pasuv[1]<ResoV1 && pasuv[2]<ResoU2 && pasuv[3]<ResoV2) {
3216 return(IntWalk_ArretSurPointPrecedent);
3219 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
3220 return(IntWalk_PasTropGrand);
3223 const gp_Dir2d& Tg2dcourante1 = myIntersectionOn2S.DirectionOnS1();
3224 const gp_Dir2d& Tg2dcourante2 = myIntersectionOn2S.DirectionOnS2();
3225 Cosi1 = Du1*Tg2dcourante1.X() + Dv1*Tg2dcourante1.Y();
3226 Cosi2 = Du2*Tg2dcourante2.X() + Dv2*Tg2dcourante2.Y();
3227 Ang1 = Abs(previousd1.Angle(Tg2dcourante1));
3228 Ang2 = Abs(previousd2.Angle(Tg2dcourante2));
3229 AngRef1 = AngRef2D*tolCoeff1;
3230 AngRef2 = AngRef2D*tolCoeff2;
3231 //-------------------------------------------------------
3232 //-- Test : Angle too great in space UV -----
3233 //-- Change of side -----
3234 //-------------------------------------------------------
3235 if(Cosi1*Cosi1 < CosRef1*Duv1 || Cosi2*Cosi2 < CosRef2*Duv2 || Ang1 > AngRef1 || Ang2 > AngRef2) {
3236 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
3237 if (pasuv[0]<ResoU1 && pasuv[1]<ResoV1 && pasuv[2]<ResoU2 && pasuv[3]<ResoV2)
3238 return(IntWalk_ArretSurPoint);
3240 return(IntWalk_PasTropGrand);
3244 //==================================================================================
3245 //== D e t e c t i o n o f : Step Too Small
3247 //==================================================================================
3249 //---------------------------------------
3250 //-- Estimate of the vector --
3251 //---------------------------------------
3253 Sqrt(Abs((previousd.XYZ()-TgCourante.XYZ()).SquareModulus()*aSqDist))/8.;
3255 if ( FlecheCourante<= fleche*0.5) { //-- Current step too small
3256 if(FlecheCourante>1e-16) {
3257 Ratio = 0.5*(fleche/FlecheCourante);
3262 Standard_Real pasSu1 = pasuv[0];
3263 Standard_Real pasSv1 = pasuv[1];
3264 Standard_Real pasSu2 = pasuv[2];
3265 Standard_Real pasSv2 = pasuv[3];
3268 //-- a point at U+DeltaU is required, ....
3269 //-- return a point at U + Epsilon
3270 //-- Epsilon << DeltaU.
3272 if(pasuv[0]< AbsDu1) pasuv[0] = AbsDu1;
3273 if(pasuv[1]< AbsDv1) pasuv[1] = AbsDv1;
3274 if(pasuv[2]< AbsDu2) pasuv[2] = AbsDu2;
3275 if(pasuv[3]< AbsDv2) pasuv[3] = AbsDv2;
3277 if(pasuv[0]<ResoU1) pasuv[0]=ResoU1;
3278 if(pasuv[1]<ResoV1) pasuv[1]=ResoV1;
3279 if(pasuv[2]<ResoU2) pasuv[2]=ResoU2;
3280 if(pasuv[3]<ResoV2) pasuv[3]=ResoV2;
3281 //-- if(Ratio>10.0 ) { Ratio=10.0; }
3282 Standard_Real R1,R = pasInit[0]/pasuv[0];
3283 R1= pasInit[1]/pasuv[1]; if(R1<R) R=R1;
3284 R1= pasInit[2]/pasuv[2]; if(R1<R) R=R1;
3285 R1= pasInit[3]/pasuv[3]; if(R1<R) R=R1;
3286 if(Ratio > R) Ratio=R;
3287 pasuv[0] = Min(Ratio*pasuv[0],pasInit[0]);
3288 pasuv[1] = Min(Ratio*pasuv[1],pasInit[1]);
3289 pasuv[2] = Min(Ratio*pasuv[2],pasInit[2]);
3290 pasuv[3] = Min(Ratio*pasuv[3],pasInit[3]);
3291 if (pasuv[0] != pasSu1 || pasuv[2] != pasSu2||
3292 pasuv[1] != pasSv1 || pasuv[3] != pasSv2) {
3293 if(++STATIC_BLOCAGE_SUR_PAS_TROP_GRAND > 5) {
3294 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND = 0;
3295 return IntWalk_PasTropGrand;
3298 if(aStatus == IntWalk_OK) {
3299 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND=0;
3300 //-- Try to increase the step
3304 else { //-- CurrentVector > vector*0.5
3305 if (FlecheCourante > fleche) { //-- Current step too Great
3306 Ratio = fleche/FlecheCourante;
3307 pasuv[0] = Ratio*pasuv[0];
3308 pasuv[1] = Ratio*pasuv[1];
3309 pasuv[2] = Ratio*pasuv[2];
3310 pasuv[3] = Ratio*pasuv[3];
3311 //if(++STATIC_BLOCAGE_SUR_PAS_TROP_GRAND > 5) {
3312 // STATIC_BLOCAGE_SUR_PAS_TROP_GRAND = 0;
3313 return IntWalk_PasTropGrand;
3316 else { //-- vector/2 < CurrentVector <= vector
3317 Ratio = 0.75 * (fleche / FlecheCourante);
3321 if(aStatus != IntWalk_PointConfondu)
3323 //Here, aCosBetweenTangent >= 0.0 definitely.
3326 Brief algorithm description.
3327 We have two (not-coincindent) intersection point (P1 and P2). In every point,
3328 vector of tangent (to the intersection curve) is known (vectors T1 and T2).
3329 Basing on these data, we create osculating circle.
3331 * - arc of osculating circle
3338 Let me draw your attention to the following facts:
3339 1. Vectors T1 and T2 direct FROM (not TO) points P1 and P2. Therefore,
3340 one of previously computed vector should be reversed.
3342 In this case, the absolute (!) value of the deflection between the arc of
3343 the osculating circle and the P1P2 segment can be computed as follows:
3344 e = d*(1-sin(B/2))/(2*cos(B/2)), (1)
3345 where d is the length of P1P2 segment, B is the angle between vectors T1 and T2.
3353 Later, the normal state of algorithm work is (as we apply)
3354 tolconf/2 <= e <= tolconf.
3355 In this case, we keep previous step.
3357 If e < tolconf/2 then the local curvature of the intersection curve is small.
3358 As result, the step should be increased.
3360 If e > tolconf then the step is too big. Therefore, we should decrease one.
3362 Condition (1) is equivalent to
3363 sin(B/2) = 1 - 2/(1+(d/(2*e))^2) = Fs(e),
3364 cos(B) = 1 - 2*Fs(e)^2 = Fd(e),
3365 where Fs(e)and Fd(e) are some function with parameter "deflection".
3367 Let mean that Fs(e) is decreasing function. Fd(e) is increasing function,
3368 in the range, where Fs(e) > 0.0 (i.e. when e < d/2).
3370 Now, let substitute required deflection (tolconf or tolconf/2) to z. Then
3371 it is necessary to check if e < z or if e > z.
3373 In this case, it is enough to comapare Fs(e) and Fs(z).
3374 At that Fs(e) > 0 because sin(B/2) > 0 always.
3376 Therefore, if Fs(z) < 0.0 then Fs(e) > Fs(z) ==> e < z definitely.
3377 If Fs(z) > 0.0 then we can compare Fs(z)^2 and Fs(e)^2 or, in substance,
3378 values Fd(e) and Fd(z). If Fd(e) > Fd(z) then e > z and vice versa.
3381 //Fd(e) is already known (Fd(e) == -aCosBetweenTangent)
3383 const Standard_Real anInvSqAbsArcDeflMax = 0.25*aSqDist/(tolconf*tolconf);
3384 const Standard_Real aSinB2Max = 1.0 - 2.0/(1.0 + anInvSqAbsArcDeflMax);
3386 if(aSinB2Max >= 0.0 && (aCosBetweenTangent <= 2.0 * aSinB2Max * aSinB2Max - 1.0))
3387 {//Real deflection is greater or equal than tolconf
3388 aStatus = IntWalk_PasTropGrand;
3391 {//Real deflection is less than tolconf
3392 const Standard_Real anInvSqAbsArcDeflMin = 4.0*anInvSqAbsArcDeflMax;
3393 const Standard_Real aSinB2Min = 1.0 - 2.0/(1.0 + anInvSqAbsArcDeflMin);
3395 if (theStatus != IntWalk_PasTropGrand &&
3396 ((aSinB2Min < 0.0) || (aCosBetweenTangent >= 2.0 * aSinB2Min * aSinB2Min - 1.0)))
3397 {//Real deflection is less than tolconf/2.0
3398 aStatus = IntWalk_StepTooSmall;
3402 if(aStatus == IntWalk_PasTropGrand)
3404 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
3408 if(aStatus == IntWalk_StepTooSmall)
3410 pasuv[0] = Max(pasuv[0], AbsDu1);
3411 pasuv[1] = Max(pasuv[1], AbsDv1);
3412 pasuv[2] = Max(pasuv[2], AbsDu2);
3413 pasuv[3] = Max(pasuv[3], AbsDv2);
3415 pasInit[0] = Max(pasInit[0], AbsDu1);
3416 pasInit[1] = Max(pasInit[1], AbsDv1);
3417 pasInit[2] = Max(pasInit[2], AbsDu2);
3418 pasInit[3] = Max(pasInit[3], AbsDv2);
3424 pasuv[0] = Max(myStepMin[0],Min(Min(Ratio*AbsDu1,pasuv[0]),pasInit[0]));
3425 pasuv[1] = Max(myStepMin[1],Min(Min(Ratio*AbsDv1,pasuv[1]),pasInit[1]));
3426 pasuv[2] = Max(myStepMin[2],Min(Min(Ratio*AbsDu2,pasuv[2]),pasInit[2]));
3427 pasuv[3] = Max(myStepMin[3],Min(Min(Ratio*AbsDv2,pasuv[3]),pasInit[3]));
3429 if(aStatus == IntWalk_OK) STATIC_BLOCAGE_SUR_PAS_TROP_GRAND=0;
3433 Standard_Boolean IntWalk_PWalking::
3434 TestArret(const Standard_Boolean DejaReparti,
3435 TColStd_Array1OfReal& Param,
3436 IntImp_ConstIsoparametric& ChoixIso)
3439 // test if the point of intersection set by these parameters remains in the
3440 // natural domain of each square.
3441 // if the point outpasses reframe to find the best iso (border)
3442 // that intersects easiest the other square
3443 // otherwise test if closed line is present
3446 Standard_Real Uvd[4],Uvf[4],Epsuv[4],Duv[4],Uvp[4],dv,dv2,ParC[4];
3447 Standard_Real DPc,DPb;
3448 Standard_Integer i = 0, k = 0;
3453 previousPoint.Parameters(Uvp[0],Uvp[1],Uvp[2],Uvp[3]);
3455 Standard_Real SolParam[4];
3456 myIntersectionOn2S.Point().Parameters(SolParam[0],SolParam[1],SolParam[2],SolParam[3]);
3458 Standard_Boolean Trouve = Standard_False;
3460 Uvd[0]=Um1; Uvf[0]=UM1; Uvd[1]=Vm1; Uvf[1]=VM1;
3461 Uvd[2]=Um2; Uvf[2]=UM2; Uvd[3]=Vm2; Uvf[3]=VM2;
3463 Standard_Integer im1;
3464 for ( i = 1,im1 = 0;i<=4;i++,im1++) {
3471 if (Param(i) < (Uvd[im1]-Epsuv[im1]) ||
3472 SolParam[im1] < (Uvd[im1]-Epsuv[im1])) //-- Current ----- Bound Inf ----- Previous
3474 Trouve = Standard_True; //--
3475 DPc = Uvp[im1]-Param(i); //-- Previous - Current
3476 DPb = Uvp[im1]-Uvd[im1]; //-- Previous - Bound Inf
3477 ParC[im1] = Uvd[im1]; //-- ParamCorrige
3478 dv = Param(k)-Uvp[k-1]; //-- Current - Previous (other Direction)
3480 if(dv2>RealEpsilon()) { //-- Progress at the other Direction ?
3481 Duv[im1] = DPc*DPb + dv2;
3482 Duv[im1] = Duv[im1]*Duv[im1]/(DPc*DPc+dv2)/(DPb*DPb+dv2);
3485 Duv[im1]=-1.0; //-- If no progress, do not change
3486 } //-- the choice of iso
3488 else if (Param(i) > (Uvf[im1] + Epsuv[im1]) ||
3489 SolParam[im1] > (Uvf[im1] + Epsuv[im1]))//-- Previous ----- Bound Sup ----- Current
3491 Trouve = Standard_True; //--
3492 DPc = Param(i)-Uvp[im1]; //-- Current - Previous
3493 DPb = Uvf[im1]-Uvp[im1]; //-- Bound Sup - Previous
3494 ParC[im1] = Uvf[im1]; //-- Param Corrige
3495 dv = Param(k)-Uvp[k-1]; //-- Current - Previous (other Direction)
3497 if(dv2>RealEpsilon()) { //-- Progress in other Direction ?
3498 Duv[im1] = DPc*DPb + dv2;
3499 Duv[im1] = Duv[im1]*Duv[im1]/(DPc*DPc+dv2)/(DPb*DPb+dv2);
3502 Duv[im1]=-1.0; //-- If no progress, do not change
3503 } //-- the choice of iso
3512 //--------------------------------------------------
3513 //-- One of Parameters u1,v1,u2,v2 is outside of --
3514 //-- the natural limits. --
3515 //-- Find the best direction of --
3516 //-- progress and reframe the parameters. --
3517 //--------------------------------------------------
3518 Standard_Real ddv = -1.0;
3520 for (i=0;i<=3;i++) {
3521 Param(i+1) = ParC[i];
3528 ChoixIso = ChoixRef(k);
3531 if((ParC[0]<=Uvd[0]+Epsuv[0]) || (ParC[0]>=Uvf[0]-Epsuv[0])) {
3532 ChoixIso = IntImp_UIsoparametricOnCaro1;
3534 else if((ParC[1]<=Uvd[1]+Epsuv[1]) || (ParC[1]>=Uvf[1]-Epsuv[1])) {
3535 ChoixIso = IntImp_VIsoparametricOnCaro1;
3537 else if((ParC[2]<=Uvd[2]+Epsuv[2]) || (ParC[2]>=Uvf[2]-Epsuv[2])) {
3538 ChoixIso = IntImp_UIsoparametricOnCaro2;
3540 else if((ParC[3]<=Uvd[3]+Epsuv[3]) || (ParC[3]>=Uvf[3]-Epsuv[3])) {
3541 ChoixIso = IntImp_VIsoparametricOnCaro2;
3544 close = Standard_False;
3545 return Standard_True;
3549 if (!DejaReparti) { // find if line closed
3552 const IntSurf_PntOn2S& POn2S1=line->Value(1);
3554 POn2S1.ParametersOnS1(u,v);
3555 gp_Pnt2d P1uvS1(u,v);
3556 previousPoint.ParametersOnS1(u,v);
3557 gp_Pnt2d PrevuvS1(u,v);
3558 myIntersectionOn2S.Point().ParametersOnS1(u,v);
3559 gp_Pnt2d myIntersuvS1(u,v);
3560 Standard_Boolean close2dS1 = (P1uvS1.XY()-PrevuvS1.XY())*
3561 (P1uvS1.XY()-myIntersuvS1.XY()) < 0.0;
3563 POn2S1.ParametersOnS2(u,v);
3564 gp_Pnt2d P1uvS2(u,v);
3565 previousPoint.ParametersOnS2(u,v);
3566 gp_Pnt2d PrevuvS2(u,v);
3567 myIntersectionOn2S.Point().ParametersOnS2(u,v);
3568 gp_Pnt2d myIntersuvS2(u,v);
3569 Standard_Boolean close2dS2 = (P1uvS2.XY()-PrevuvS2.XY())*
3570 (P1uvS2.XY()-myIntersuvS2.XY()) < 0.0;
3572 close = close2dS1 && close2dS2;
3575 else return Standard_False;