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 static const Standard_Real CosRef3D = 0.98;// rule by tests in U4
17 // correspond to 11.478 d
18 static const Standard_Real CosRef2D = 0.88; // correspond to 25 d
19 static const Standard_Integer MaxDivision = 60; // max number of step division
20 // because the angle is too great in 2d (U4)
23 IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
25 const Standard_Boolean Finished,
26 const math_Vector& UV,
27 const IntWalk_StatusDeflection StatusPrecedent,
28 Standard_Integer& NbDivision,
30 const Standard_Integer StepSign)
32 // Check the step of advancement, AND recalculate this step :
34 // 1) test point confused
35 // if yes other tests are not done
36 // 2) test angle 3d too great
37 // if yes divide the step and leave
38 // angle3d = angle ((previous point, calculated point),
40 // 3) check step of advancement in 2d
41 // 4) test point confused
42 // 5) test angle 2d too great
43 // 6) test point of tangency
45 // 7) calculate the tangent by u,v of the section
46 // 8) test angle 3d too great
47 // angle3d = angle ((previous point, calculated point),
49 // 9) test angle 2d too great
50 //10) test change of side (pass the tangent point not knowing it)
51 //11) calculate the step of advancement depending on the vector
52 //12) adjust the step depending on the previous steps
54 IntWalk_StatusDeflection Status = IntWalk_OK;
56 //---------------------------------------------------------------------------------
57 //-- lbr le 4 Avril 95 : it is possible that the status returns points confused
58 //-- if epsilon is great enough (1e-11). In this case one loops
59 //-- without ever changing the values sent to Rsnld.
60 //---------------------------------------------------------------------------------
61 Standard_Real Paramu = 0.0, Paramv = 0.0;
64 previousPoint.ParametersOnS2(Paramu, Paramv);
68 previousPoint.ParametersOnS1(Paramu, Paramv);
71 const Standard_Real Du = UV(1) - Paramu;
72 const Standard_Real Dv = UV(2) - Paramv;
73 const Standard_Real Duv = Du * Du + Dv * Dv;
75 gp_Vec Corde(previousPoint.Value(), sp.Point());
77 const Standard_Real Norme = Corde.SquareMagnitude(),
78 aTol = epsilon*Precision::PConfusion();
80 //if ((++NbPointsConfondusConsecutifs < 10) && (Norme <= epsilon)) { // the square is already taken in the constructor
81 if ((Norme <= epsilon) && ((Duv <= aTol) || (StatusPrecedent != IntWalk_OK)))
82 { // the square is already taken in the constructor
83 Status = IntWalk_PointConfondu;
84 if (StatusPrecedent == IntWalk_PasTropGrand) {
85 return IntWalk_ArretSurPointPrecedent;
89 Standard_Real Cosi = Corde * previousd3d;
90 Standard_Real Cosi2 = 0.0;
92 if (Cosi*StepSign >= 0.) {// angle 3d <= pi/2 !!!!
93 const Standard_Real aDiv = previousd3d.SquareMagnitude()*Norme;
96 Cosi2 = Cosi * Cosi / aDiv;
98 if (Cosi2 < CosRef3D) { //angle 3d too great
100 Standard_Real StepU = Abs(Step*previousd2d.X()),
101 StepV = Abs(Step*previousd2d.Y());
102 if (StepU < tolerance(1) && StepV < tolerance(2))
103 Status = IntWalk_ArretSurPointPrecedent;
105 Status = IntWalk_PasTropGrand;
110 if (Abs(Du) < tolerance(1) && Abs(Dv) < tolerance(2))
111 return IntWalk_ArretSurPointPrecedent; //confused point 2d
113 Standard_Real Cosi = StepSign * (Du * previousd2d.X() + Dv * previousd2d.Y());
115 if (Cosi < 0 && Status == IntWalk_PointConfondu)
116 return IntWalk_ArretSurPointPrecedent; // leave as step back
117 // with confused point
120 return IntWalk_ArretSurPoint;
122 //if during routing one has subdivided more than MaxDivision for each
123 //previous step, bug on the square; do nothing (experience U4)
125 if ((NbDivision < MaxDivision) && (Status != IntWalk_PointConfondu) &&
126 (StatusPrecedent!= IntWalk_PointConfondu))
128 Standard_Real Cosi2 = Cosi * Cosi / Duv;
129 if (Cosi2 < CosRef2D || Cosi < 0 ) {
131 Standard_Real StepU = Abs(Step*previousd2d.X()),
132 StepV = Abs(Step*previousd2d.Y());
134 if (StepU < tolerance(1) && StepV < tolerance(2))
135 Status = IntWalk_ArretSurPointPrecedent;
137 Status = IntWalk_PasTropGrand;
138 NbDivision = NbDivision + 1;
142 Cosi = Corde * sp.Direction3d();
143 Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
144 if (Cosi2 < CosRef3D ){ //angle 3d too great
146 Standard_Real StepU = Abs(Step*previousd2d.X()),
147 StepV = Abs(Step*previousd2d.Y());
148 if (StepU < tolerance(1) && StepV < tolerance(2))
149 Status = IntWalk_ArretSurPoint;
151 Status = IntWalk_PasTropGrand;
154 Cosi = Du * sp.Direction2d().X() +
155 Dv * sp.Direction2d().Y();
156 Cosi2 = Cosi * Cosi / Duv;
157 if (Cosi2 < CosRef2D ||
158 sp.Direction2d() * previousd2d < 0) {
159 //angle 2d too great or change the side
161 Standard_Real StepU = Abs(Step*previousd2d.X()),
162 StepV = Abs(Step*previousd2d.Y());
163 if (StepU < tolerance(1) && StepV < tolerance(2))
164 Status = IntWalk_ArretSurPointPrecedent;
166 Status = IntWalk_PasTropGrand;
172 if (Status == IntWalk_PointConfondu)
174 Standard_Real StepU = Min(Abs(1.5 * Du),pas*(UM-Um)),
175 StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
177 Standard_Real d2dx = Abs(previousd2d.X());
178 Standard_Real d2dy = Abs(previousd2d.Y());
180 if (d2dx < tolerance(1))
184 else if (d2dy < tolerance(2))
190 Step = Min(StepU/d2dx,StepV/d2dy);
195 // estimate the current vector.
196 // if vector/2<=current vector<= vector it is considered that the criterion
198 // otherwise adjust the step depending on the previous step
201 Standard_Real Dist = Sqrt(Norme)/3.;
202 TColgp_Array1OfPnt Poles(1,4);
203 gp_Pnt POnCurv,Milieu;
204 Poles(1) = previousPoint.Value();
205 Poles(4) = sp.Point();
206 Poles(2) = Poles(1).XYZ() +
207 StepSign * Dist* previousd3d.Normalized().XYZ();
208 Poles(3) = Poles(4).XYZ() -
209 StepSign * Dist*sp.Direction3d().Normalized().XYZ();
210 BzCLib::PntPole(0.5,Poles,POnCurv);
211 Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
212 // FlecheCourante = Milieu.Distance(POnCurv);
213 Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
216 // Direct calculation :
217 // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
218 // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
219 // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
220 // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
221 // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
222 // the norm (square) of 3.*lambda (d1 - d4)/8.
223 // either the norm of :
224 // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
225 // which produces, takin the square :
226 // Norme * (d1-d4).SquareMagnitude()/64.
228 Standard_Real FlecheCourante =
229 (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
232 // if (FlecheCourante <= 0.5*fleche) {
233 if (FlecheCourante <= 0.25*fleche*fleche)
235 Standard_Real d2dx = Abs(sp.Direction2d().X());
236 Standard_Real d2dy = Abs(sp.Direction2d().Y());
238 Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
239 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
241 if (d2dx < tolerance(1))
245 else if (d2dy < tolerance(2))
251 Step = Min(StepU/d2dx,StepV/d2dy);
256 //if (FlecheCourante > fleche) { // step too great
257 if (FlecheCourante > fleche*fleche)
260 Standard_Real StepU = Abs(Step*previousd2d.X()),
261 StepV = Abs(Step*previousd2d.Y());
263 if (StepU < tolerance(1) && StepV < tolerance(2))
264 Status = IntWalk_ArretSurPointPrecedent;
266 Status = IntWalk_PasTropGrand;
270 Standard_Real d2dx = Abs(sp.Direction2d().X());
271 Standard_Real d2dy = Abs(sp.Direction2d().Y());
273 Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
274 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
276 if (d2dx < tolerance(1))
278 Step = Min(Step,StepV/d2dy);
280 else if (d2dy < tolerance(2))
282 Step = Min(Step,StepU/d2dx);
286 Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));