Commit | Line | Data |
---|---|---|
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 | 15 | namespace { |
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 | 23 | IntWalk_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 |