0026632: HLR sample doesn't work with Algo mode
[occt.git] / src / IntWalk / IntWalk_IWalking_5.gxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 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
973c2be1 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.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
1ef32e96 15namespace {
b1c5c4e6 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)
1ef32e96
RL
21}
22
7fd59977 23IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
24 (TheIWFunction& sp,
25 const Standard_Boolean Finished,
26 const math_Vector& UV,
27 const IntWalk_StatusDeflection StatusPrecedent,
28 Standard_Integer& NbDivision,
29 Standard_Real& Step,
30 const Standard_Integer StepSign)
31{
b1c5c4e6 32 // Check the step of advancement, AND recalculate this step :
7fd59977 33 //
b1c5c4e6 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),
39 // previous tangent)
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
44 // if yes leave
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),
48 // new tangent)
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
7fd59977 53
54 IntWalk_StatusDeflection Status = IntWalk_OK;
55
7fd59977 56 //---------------------------------------------------------------------------------
b1c5c4e6 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.
7fd59977 60 //---------------------------------------------------------------------------------
b92f3572 61 Standard_Real Paramu = 0.0, Paramv = 0.0;
62
63 if (!reversed) {
64 previousPoint.ParametersOnS2(Paramu, Paramv);
65 }
66 else
67 {
68 previousPoint.ParametersOnS1(Paramu, Paramv);
69 }
70
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;
7fd59977 74
75 gp_Vec Corde(previousPoint.Value(), sp.Point());
76
b92f3572 77 const Standard_Real Norme = Corde.SquareMagnitude(),
78 aTol = epsilon*Precision::PConfusion();
79
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
7fd59977 83 Status = IntWalk_PointConfondu;
84 if (StatusPrecedent == IntWalk_PasTropGrand) {
85 return IntWalk_ArretSurPointPrecedent;
86 }
7fd59977 87 }
88 else {
b92f3572 89 Standard_Real Cosi = Corde * previousd3d;
90 Standard_Real Cosi2 = 0.0;
91
92 if (Cosi*StepSign >= 0.) {// angle 3d <= pi/2 !!!!
93 const Standard_Real aDiv = previousd3d.SquareMagnitude()*Norme;
94 if(aDiv == 0)
95 return Status;
96 Cosi2 = Cosi * Cosi / aDiv;
7fd59977 97 }
b1c5c4e6 98 if (Cosi2 < CosRef3D) { //angle 3d too great
7fd59977 99 Step = Step /2.0;
b92f3572 100 Standard_Real StepU = Abs(Step*previousd2d.X()),
101 StepV = Abs(Step*previousd2d.Y());
7fd59977 102 if (StepU < tolerance(1) && StepV < tolerance(2))
b92f3572 103 Status = IntWalk_ArretSurPointPrecedent;
7fd59977 104 else
b92f3572 105 Status = IntWalk_PasTropGrand;
7fd59977 106 return Status;
107 }
108 }
109
c0e32b3c 110 const Standard_Real aMinTolU = 0.1*Abs(Step*previousd2d.X()),
111 aMinTolV = 0.1*Abs(Step*previousd2d.Y());
657ccd95 112 const Standard_Real aTolU = (aMinTolU > 0.0) ? Min(tolerance(1), aMinTolU) : tolerance(1),
113 aTolV = (aMinTolV > 0.0) ? Min(tolerance(2), aMinTolV) : tolerance(2);
c0e32b3c 114
657ccd95 115 //If aMinTolU==0.0 then (Abs(Du) < aMinTolU) is equivalent of (Abs(Du) < 0.0).
116 //It is impossible. Therefore, this case should be processed separately.
117 //Analogicaly for aMinTolV.
118
119 if ((Abs(Du) < aTolU) && (Abs(Dv) < aTolV))
c0e32b3c 120 {
121 //Thin shapes (for which Ulast-Ufirst or/and Vlast-Vfirst is quite small)
122 //exists (see bug #25820). In this case, step is quite small too.
123 //Nevertheless, it not always means that we mark time. Therefore, Du and Dv
124 //must consider step (aMinTolU and aMinTolV parameters).
125
b1c5c4e6 126 return IntWalk_ArretSurPointPrecedent; //confused point 2d
c0e32b3c 127 }
b92f3572 128
129 Standard_Real Cosi = StepSign * (Du * previousd2d.X() + Dv * previousd2d.Y());
130
7fd59977 131 if (Cosi < 0 && Status == IntWalk_PointConfondu)
b1c5c4e6 132 return IntWalk_ArretSurPointPrecedent; // leave as step back
133 // with confused point
7fd59977 134
7fd59977 135 if (sp.IsTangent())
136 return IntWalk_ArretSurPoint;
137
b1c5c4e6 138//if during routing one has subdivided more than MaxDivision for each
139//previous step, bug on the square; do nothing (experience U4)
7fd59977 140
b92f3572 141 if ((NbDivision < MaxDivision) && (Status != IntWalk_PointConfondu) &&
142 (StatusPrecedent!= IntWalk_PointConfondu))
143 {
144 Standard_Real Cosi2 = Cosi * Cosi / Duv;
7fd59977 145 if (Cosi2 < CosRef2D || Cosi < 0 ) {
146 Step = Step / 2.0;
b92f3572 147 Standard_Real StepU = Abs(Step*previousd2d.X()),
148 StepV = Abs(Step*previousd2d.Y());
7fd59977 149
150 if (StepU < tolerance(1) && StepV < tolerance(2))
b92f3572 151 Status = IntWalk_ArretSurPointPrecedent;
7fd59977 152 else
b92f3572 153 Status = IntWalk_PasTropGrand;
7fd59977 154 NbDivision = NbDivision + 1;
155 return Status;
156 }
157
158 Cosi = Corde * sp.Direction3d();
159 Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
b1c5c4e6 160 if (Cosi2 < CosRef3D ){ //angle 3d too great
7fd59977 161 Step = Step / 2.;
b92f3572 162 Standard_Real StepU = Abs(Step*previousd2d.X()),
163 StepV = Abs(Step*previousd2d.Y());
7fd59977 164 if (StepU < tolerance(1) && StepV < tolerance(2))
b92f3572 165 Status = IntWalk_ArretSurPoint;
7fd59977 166 else
b92f3572 167 Status = IntWalk_PasTropGrand;
7fd59977 168 return Status;
169 }
170 Cosi = Du * sp.Direction2d().X() +
b92f3572 171 Dv * sp.Direction2d().Y();
7fd59977 172 Cosi2 = Cosi * Cosi / Duv;
173 if (Cosi2 < CosRef2D ||
b92f3572 174 sp.Direction2d() * previousd2d < 0) {
175 //angle 2d too great or change the side
176 Step = Step / 2.;
177 Standard_Real StepU = Abs(Step*previousd2d.X()),
178 StepV = Abs(Step*previousd2d.Y());
179 if (StepU < tolerance(1) && StepV < tolerance(2))
180 Status = IntWalk_ArretSurPointPrecedent;
181 else
182 Status = IntWalk_PasTropGrand;
183 return Status;
7fd59977 184 }
185 }
186
187 if (!Finished) {
b92f3572 188 if (Status == IntWalk_PointConfondu)
189 {
190 Standard_Real StepU = Min(Abs(1.5 * Du),pas*(UM-Um)),
191 StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
7fd59977 192
193 Standard_Real d2dx = Abs(previousd2d.X());
194 Standard_Real d2dy = Abs(previousd2d.Y());
195
b92f3572 196 if (d2dx < tolerance(1))
197 {
198 Step = StepV/d2dy;
7fd59977 199 }
b92f3572 200 else if (d2dy < tolerance(2))
201 {
202 Step = StepU/d2dx;
7fd59977 203 }
b92f3572 204 else
205 {
206 Step = Min(StepU/d2dx,StepV/d2dy);
7fd59977 207 }
7fd59977 208 }
b92f3572 209 else
210 {
211 // estimate the current vector.
212 // if vector/2<=current vector<= vector it is considered that the criterion
213 // is observed.
214 // otherwise adjust the step depending on the previous step
215
216 /*
217 Standard_Real Dist = Sqrt(Norme)/3.;
218 TColgp_Array1OfPnt Poles(1,4);
219 gp_Pnt POnCurv,Milieu;
220 Poles(1) = previousPoint.Value();
221 Poles(4) = sp.Point();
222 Poles(2) = Poles(1).XYZ() +
223 StepSign * Dist* previousd3d.Normalized().XYZ();
224 Poles(3) = Poles(4).XYZ() -
225 StepSign * Dist*sp.Direction3d().Normalized().XYZ();
226 BzCLib::PntPole(0.5,Poles,POnCurv);
227 Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
228 // FlecheCourante = Milieu.Distance(POnCurv);
229 Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
230 */
231
232 // Direct calculation :
233 // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
234 // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
235 // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
236 // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
237 // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
238 // the norm (square) of 3.*lambda (d1 - d4)/8.
239 // either the norm of :
240 // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
241 // which produces, takin the square :
242 // Norme * (d1-d4).SquareMagnitude()/64.
7fd59977 243
244 Standard_Real FlecheCourante =
245 (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
246
247
248// if (FlecheCourante <= 0.5*fleche) {
b92f3572 249 if (FlecheCourante <= 0.25*fleche*fleche)
250 {
251 Standard_Real d2dx = Abs(sp.Direction2d().X());
252 Standard_Real d2dy = Abs(sp.Direction2d().Y());
253
254 Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
255 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
256
257 if (d2dx < tolerance(1))
258 {
259 Step = StepV/d2dy;
260 }
261 else if (d2dy < tolerance(2))
262 {
263 Step = StepU/d2dx;
264 }
265 else
266 {
267 Step = Min(StepU/d2dx,StepV/d2dy);
268 }
7fd59977 269 }
b92f3572 270 else
271 {
272 //if (FlecheCourante > fleche) { // step too great
273 if (FlecheCourante > fleche*fleche)
274 { // step too great
275 Step = Step /2.;
276 Standard_Real StepU = Abs(Step*previousd2d.X()),
277 StepV = Abs(Step*previousd2d.Y());
278
de09d2a2 279 if (StepU < tolerance(1) && StepV < tolerance(2))
280 Status = IntWalk_ArretSurPointPrecedent;
281 else
282 Status = IntWalk_PasTropGrand;
b92f3572 283 }
284 else
285 {
286 Standard_Real d2dx = Abs(sp.Direction2d().X());
287 Standard_Real d2dy = Abs(sp.Direction2d().Y());
288
289 Standard_Real StepU = Min(Abs(1.5*Du),pas*(UM-Um)),
290 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
291
292 if (d2dx < tolerance(1))
293 {
294 Step = Min(Step,StepV/d2dy);
295 }
296 else if (d2dy < tolerance(2))
297 {
298 Step = Min(Step,StepU/d2dx);
299 }
300 else
301 {
302 Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
303 }
304 }
7fd59977 305 }
306 }
307 }
308 return Status;
309}
310
311
312
313