Integration of OCCT 6.5.0 from SVN
[occt.git] / src / IntWalk / IntWalk_IWalking_5.gxx
... / ...
CommitLineData
1IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
2 (TheIWFunction& sp,
3 const Standard_Boolean Finished,
4 const math_Vector& UV,
5 const IntWalk_StatusDeflection StatusPrecedent,
6 Standard_Integer& NbDivision,
7 Standard_Real& Step,
8 const Standard_Integer StepSign)
9{
10 // Verification du pas d avancement, ET recalcul de ce pas :
11 //
12 // 1)test point confondu
13 // si oui les autres tests ne sont pas faits
14 // 2)test angle 3d trop grand
15 // si oui on divise le pas, on sort
16 // angle3d = angle ((point precedent, point calcule),
17 // tangente precedente)
18 // 3)verification du pas d avancement en 2d
19 // 4)test point confondu
20 // 5)test angle 2d trop grand
21 // 6)test point de tangence
22 // si oui on sort
23 // 7)calcul de la tangente en u,v de la section
24 // 8)test angle 3d trop grand
25 // angle3d = angle ((point precedent, point calcule),
26 // nouvelle tangente)
27 // 9)test angle 2d trop grand
28 //10)test de changement de rive(depasser le point de tangence sans le savoir)
29 //11)calcul du pas d avancement en fonction de la fleche
30 //12)ajustement du pas en fonction des pas precedents
31
32 IntWalk_StatusDeflection Status = IntWalk_OK;
33
34 static const Standard_Real CosRef3D = 0.98;// regle par tests dans U4
35 // correspond a 11.478 d
36 static const Standard_Real CosRef2D = 0.88; // correspond a 25 d
37 static const Standard_Integer MaxDivision = 60; // nombre maxi de division
38 // du pas a cause de
39 // l angle trop grand en 2d (U4)
40 //---------------------------------------------------------------------------------
41 //-- lbr le 4 Avril 95 : On peut se trouver ds le cas ou Status renvoie point
42 //-- confondus si epsilon est assez grand (1e-11) . Dans ce cas on boucle
43 //-- sans jamais changer les valeurs envoyees a Rsnld.
44 static Standard_Integer NbPointsConfondusConsecutifs = 0 ;
45 static Standard_Integer EpsilonSembleTropGrand = 0 ;
46 //---------------------------------------------------------------------------------
47 Standard_Real Paramu, Paramv, StepU,StepV;
48 Standard_Real Cosi, Cosi2, Norme;
49
50 gp_Vec Corde(previousPoint.Value(), sp.Point());
51
52 Norme = Corde.SquareMagnitude();
53// if (Norme <= epsilon*epsilon) {
54 if ((++NbPointsConfondusConsecutifs < 10) && (Norme <= epsilon)) { // le carre est deja pris dans le constructeur
55 Status = IntWalk_PointConfondu;
56 if (StatusPrecedent == IntWalk_PasTropGrand) {
57 return IntWalk_ArretSurPointPrecedent;
58 }
59
60 if(++EpsilonSembleTropGrand > 5 && NbPointsConfondusConsecutifs == 8) { //-- Provisoire
61 if(epsilon>0.00000000001) epsilon*=0.5; //-- Provisoire
62 EpsilonSembleTropGrand = 0; //-- Provisoire
63 }
64 }
65 else {
66 NbPointsConfondusConsecutifs = 0; //-- Provisoire
67 EpsilonSembleTropGrand = 0; //-- Provisoire
68 if(Norme<1e-16) Norme = 1e-16; //-- Provisoire
69
70 Cosi = Corde * previousd3d;
71 if (Cosi*StepSign < 0.) { // angle 3d > pi/2 !!!!
72 Cosi2 = 0.;
73 }
74 else {
75 Cosi2 = Cosi * Cosi / previousd3d.SquareMagnitude() / Norme;
76 }
77 if (Cosi2 < CosRef3D) { //angle 3d trop grand
78 Step = Step /2.0;
79 StepU = Abs(Step*previousd2d.X());
80 StepV = Abs(Step*previousd2d.Y());
81 if (StepU < tolerance(1) && StepV < tolerance(2))
82 Status = IntWalk_ArretSurPointPrecedent;
83 else
84 Status = IntWalk_PasTropGrand;
85 return Status;
86 }
87 }
88
89 if (!reversed) {
90 previousPoint.ParametersOnS2(Paramu, Paramv);
91 }
92 else {
93 previousPoint.ParametersOnS1(Paramu, Paramv);
94 }
95 Standard_Real Du = UV(1) - Paramu;
96 Standard_Real Dv = UV(2) - Paramv;
97 Standard_Real Duv = Du * Du + Dv * Dv;
98 if (Abs(Du) < tolerance(1) && Abs(Dv) < tolerance(2))
99 return IntWalk_ArretSurPointPrecedent; //point confondu 2d
100 Cosi = StepSign * (Du * previousd2d.X() +
101 Dv * previousd2d.Y());
102 if (Cosi < 0 && Status == IntWalk_PointConfondu)
103 return IntWalk_ArretSurPointPrecedent; // on sort car retour arriere
104 // avec point confondu
105
106
107 if (sp.IsTangent())
108 return IntWalk_ArretSurPoint;
109
110//si au cours du cheminement on a subdivise plus de MaxDivision pour chaque
111//pas precedent,anomalie sur le carreau;on ne fait plus rien (experience U4)
112
113 if (NbDivision < MaxDivision &&
114 Status != IntWalk_PointConfondu &&
115 StatusPrecedent!= IntWalk_PointConfondu ) {
116 Cosi2 = Cosi * Cosi / Duv;
117 if (Cosi2 < CosRef2D || Cosi < 0 ) {
118 Step = Step / 2.0;
119 StepU = Abs(Step*previousd2d.X());
120 StepV = Abs(Step*previousd2d.Y());
121
122 if (StepU < tolerance(1) && StepV < tolerance(2))
123 Status = IntWalk_ArretSurPointPrecedent;
124 else
125 Status = IntWalk_PasTropGrand;
126 NbDivision = NbDivision + 1;
127 return Status;
128 }
129
130 Cosi = Corde * sp.Direction3d();
131 Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
132 if (Cosi2 < CosRef3D ){ //angle 3d trop grand
133 Step = Step / 2.;
134 StepU = Abs(Step*previousd2d.X());
135 StepV = Abs(Step*previousd2d.Y());
136 if (StepU < tolerance(1) && StepV < tolerance(2))
137 Status = IntWalk_ArretSurPoint;
138 else
139 Status = IntWalk_PasTropGrand;
140 return Status;
141 }
142 Cosi = Du * sp.Direction2d().X() +
143 Dv * sp.Direction2d().Y();
144 Cosi2 = Cosi * Cosi / Duv;
145 if (Cosi2 < CosRef2D ||
146 sp.Direction2d() * previousd2d < 0) {
147 //angle 2d trop grand ou changement de rive
148 Step = Step / 2.;
149 StepU = Abs(Step*previousd2d.X());
150 StepV = Abs(Step*previousd2d.Y());
151 if (StepU < tolerance(1) && StepV < tolerance(2))
152 Status = IntWalk_ArretSurPointPrecedent;
153 else
154 Status = IntWalk_PasTropGrand;
155 return Status;
156 }
157 }
158
159 if (!Finished) {
160
161 if (Status == IntWalk_PointConfondu) {
162 StepU = Min(Abs(1.5 * Du),pas*(UM-Um));
163 StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
164
165 Standard_Real d2dx = Abs(previousd2d.X());
166 Standard_Real d2dy = Abs(previousd2d.Y());
167
168 if (d2dx < tolerance(1)) {
169 Step = StepV/d2dy;
170 }
171 else if (d2dy < tolerance(2)) {
172 Step = StepU/d2dx;
173 }
174 else {
175 Step = Min(StepU/d2dx,StepV/d2dy);
176 }
177
178
179
180 }
181 else {
182// on estime la fleche courante.
183// si fleche/2<=flechecourante<= fleche on considere que le critere est
184// respecte.
185// sinon ajuster le pas en fonction du pas precedent
186
187/*
188 Standard_Real Dist = Sqrt(Norme)/3.;
189 TColgp_Array1OfPnt Poles(1,4);
190 gp_Pnt POnCurv,Milieu;
191 Poles(1) = previousPoint.Value();
192 Poles(4) = sp.Point();
193 Poles(2) = Poles(1).XYZ() +
194 StepSign * Dist* previousd3d.Normalized().XYZ();
195 Poles(3) = Poles(4).XYZ() -
196 StepSign * Dist*sp.Direction3d().Normalized().XYZ();
197 BzCLib::PntPole(0.5,Poles,POnCurv);
198 Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
199// FlecheCourante = Milieu.Distance(POnCurv);
200 Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
201*/
202
203 // Calcul direct :
204 // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
205 // soit POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
206 // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
207 // Donc POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
208 // On calcule l'ecart avec (p1+p4)/2. . Il faut donc juste calculer
209 // la norme (au carre) de 3.*lambda (d1 - d4)/8.
210 // soit la norme de :
211 // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
212 // ce qui fait, en prenant le carre :
213 // Norme * (d1-d4).SquareMagnitude()/64.
214
215 Standard_Real FlecheCourante =
216 (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
217
218
219// if (FlecheCourante <= 0.5*fleche) {
220 if (FlecheCourante <= 0.25*fleche*fleche) {
221
222 Standard_Real d2dx = Abs(sp.Direction2d().X());
223 Standard_Real d2dy = Abs(sp.Direction2d().Y());
224
225 StepU = Min(Abs(1.5*Du),pas*(UM-Um));
226 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
227
228 if (d2dx < tolerance(1)) {
229 Step = StepV/d2dy;
230 }
231 else if (d2dy < tolerance(2)) {
232 Step = StepU/d2dx;
233 }
234 else {
235 Step = Min(StepU/d2dx,StepV/d2dy);
236 }
237
238 }
239 else {
240// if (FlecheCourante > fleche) { // pas trop grand
241 if (FlecheCourante > fleche*fleche) { // pas trop grand
242 Step = Step /2.;
243 Status = IntWalk_PasTropGrand;
244 }
245 else {
246 Standard_Real d2dx = Abs(sp.Direction2d().X());
247 Standard_Real d2dy = Abs(sp.Direction2d().Y());
248
249 StepU = Min(Abs(1.5*Du),pas*(UM-Um));
250 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
251
252 if (d2dx < tolerance(1)) {
253 Step = Min(Step,StepV/d2dy);
254 }
255 else if (d2dy < tolerance(2)) {
256 Step = Min(Step,StepU/d2dx);
257 }
258 else {
259 Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
260 }
261 }
262 }
263 }
264 }
265 return Status;
266}
267
268
269
270