0023952: Improving thread-safety of intersections, approximations and other modeling...
[occt.git] / src / IntWalk / IntWalk_IWalking_5.gxx
CommitLineData
b311480e 1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2012 OPEN CASCADE SAS
3//
4// The content of this file is subject to the Open CASCADE Technology Public
5// License Version 6.5 (the "License"). You may not use the content of this file
6// except in compliance with the License. Please obtain a copy of the License
7// at http://www.opencascade.org and read it completely before using this file.
8//
9// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11//
12// The Original Code and all software distributed under the License is
13// distributed on an "AS IS" basis, without warranty of any kind, and the
14// Initial Developer hereby disclaims all such warranties, including without
15// limitation, any warranties of merchantability, fitness for a particular
16// purpose or non-infringement. Please see the License for the specific terms
17// and conditions governing the rights and limitations under the License.
18
1ef32e96
RL
19namespace {
20 static const Standard_Real CosRef3D = 0.98;// regle par tests dans U4
21 // correspond a 11.478 d
22 static const Standard_Real CosRef2D = 0.88; // correspond a 25 d
23 static const Standard_Integer MaxDivision = 60; // nombre maxi de division
24 // du pas a cause de
25 // l angle trop grand en 2d (U4)
26}
27
7fd59977 28IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
29 (TheIWFunction& sp,
30 const Standard_Boolean Finished,
31 const math_Vector& UV,
32 const IntWalk_StatusDeflection StatusPrecedent,
33 Standard_Integer& NbDivision,
34 Standard_Real& Step,
35 const Standard_Integer StepSign)
36{
37 // Verification du pas d avancement, ET recalcul de ce pas :
38 //
39 // 1)test point confondu
40 // si oui les autres tests ne sont pas faits
41 // 2)test angle 3d trop grand
42 // si oui on divise le pas, on sort
43 // angle3d = angle ((point precedent, point calcule),
44 // tangente precedente)
45 // 3)verification du pas d avancement en 2d
46 // 4)test point confondu
47 // 5)test angle 2d trop grand
48 // 6)test point de tangence
49 // si oui on sort
50 // 7)calcul de la tangente en u,v de la section
51 // 8)test angle 3d trop grand
52 // angle3d = angle ((point precedent, point calcule),
53 // nouvelle tangente)
54 // 9)test angle 2d trop grand
55 //10)test de changement de rive(depasser le point de tangence sans le savoir)
56 //11)calcul du pas d avancement en fonction de la fleche
57 //12)ajustement du pas en fonction des pas precedents
58
59 IntWalk_StatusDeflection Status = IntWalk_OK;
60
7fd59977 61 //---------------------------------------------------------------------------------
62 //-- lbr le 4 Avril 95 : On peut se trouver ds le cas ou Status renvoie point
63 //-- confondus si epsilon est assez grand (1e-11) . Dans ce cas on boucle
64 //-- sans jamais changer les valeurs envoyees a Rsnld.
7fd59977 65 //---------------------------------------------------------------------------------
66 Standard_Real Paramu, Paramv, StepU,StepV;
67 Standard_Real Cosi, Cosi2, Norme;
68
69 gp_Vec Corde(previousPoint.Value(), sp.Point());
70
71 Norme = Corde.SquareMagnitude();
72// if (Norme <= epsilon*epsilon) {
73 if ((++NbPointsConfondusConsecutifs < 10) && (Norme <= epsilon)) { // le carre est deja pris dans le constructeur
74 Status = IntWalk_PointConfondu;
75 if (StatusPrecedent == IntWalk_PasTropGrand) {
76 return IntWalk_ArretSurPointPrecedent;
77 }
78
79 if(++EpsilonSembleTropGrand > 5 && NbPointsConfondusConsecutifs == 8) { //-- Provisoire
80 if(epsilon>0.00000000001) epsilon*=0.5; //-- Provisoire
81 EpsilonSembleTropGrand = 0; //-- Provisoire
82 }
83 }
84 else {
85 NbPointsConfondusConsecutifs = 0; //-- Provisoire
86 EpsilonSembleTropGrand = 0; //-- Provisoire
87 if(Norme<1e-16) Norme = 1e-16; //-- Provisoire
88
89 Cosi = Corde * previousd3d;
90 if (Cosi*StepSign < 0.) { // angle 3d > pi/2 !!!!
91 Cosi2 = 0.;
92 }
93 else {
94 Cosi2 = Cosi * Cosi / previousd3d.SquareMagnitude() / Norme;
95 }
96 if (Cosi2 < CosRef3D) { //angle 3d trop grand
97 Step = Step /2.0;
98 StepU = Abs(Step*previousd2d.X());
99 StepV = Abs(Step*previousd2d.Y());
100 if (StepU < tolerance(1) && StepV < tolerance(2))
101 Status = IntWalk_ArretSurPointPrecedent;
102 else
103 Status = IntWalk_PasTropGrand;
104 return Status;
105 }
106 }
107
108 if (!reversed) {
109 previousPoint.ParametersOnS2(Paramu, Paramv);
110 }
111 else {
112 previousPoint.ParametersOnS1(Paramu, Paramv);
113 }
114 Standard_Real Du = UV(1) - Paramu;
115 Standard_Real Dv = UV(2) - Paramv;
116 Standard_Real Duv = Du * Du + Dv * Dv;
117 if (Abs(Du) < tolerance(1) && Abs(Dv) < tolerance(2))
118 return IntWalk_ArretSurPointPrecedent; //point confondu 2d
119 Cosi = StepSign * (Du * previousd2d.X() +
120 Dv * previousd2d.Y());
121 if (Cosi < 0 && Status == IntWalk_PointConfondu)
122 return IntWalk_ArretSurPointPrecedent; // on sort car retour arriere
123 // avec point confondu
124
125
126 if (sp.IsTangent())
127 return IntWalk_ArretSurPoint;
128
129//si au cours du cheminement on a subdivise plus de MaxDivision pour chaque
130//pas precedent,anomalie sur le carreau;on ne fait plus rien (experience U4)
131
132 if (NbDivision < MaxDivision &&
133 Status != IntWalk_PointConfondu &&
134 StatusPrecedent!= IntWalk_PointConfondu ) {
135 Cosi2 = Cosi * Cosi / Duv;
136 if (Cosi2 < CosRef2D || Cosi < 0 ) {
137 Step = Step / 2.0;
138 StepU = Abs(Step*previousd2d.X());
139 StepV = Abs(Step*previousd2d.Y());
140
141 if (StepU < tolerance(1) && StepV < tolerance(2))
142 Status = IntWalk_ArretSurPointPrecedent;
143 else
144 Status = IntWalk_PasTropGrand;
145 NbDivision = NbDivision + 1;
146 return Status;
147 }
148
149 Cosi = Corde * sp.Direction3d();
150 Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
151 if (Cosi2 < CosRef3D ){ //angle 3d trop grand
152 Step = Step / 2.;
153 StepU = Abs(Step*previousd2d.X());
154 StepV = Abs(Step*previousd2d.Y());
155 if (StepU < tolerance(1) && StepV < tolerance(2))
156 Status = IntWalk_ArretSurPoint;
157 else
158 Status = IntWalk_PasTropGrand;
159 return Status;
160 }
161 Cosi = Du * sp.Direction2d().X() +
162 Dv * sp.Direction2d().Y();
163 Cosi2 = Cosi * Cosi / Duv;
164 if (Cosi2 < CosRef2D ||
165 sp.Direction2d() * previousd2d < 0) {
166 //angle 2d trop grand ou changement de rive
167 Step = Step / 2.;
168 StepU = Abs(Step*previousd2d.X());
169 StepV = Abs(Step*previousd2d.Y());
170 if (StepU < tolerance(1) && StepV < tolerance(2))
171 Status = IntWalk_ArretSurPointPrecedent;
172 else
173 Status = IntWalk_PasTropGrand;
174 return Status;
175 }
176 }
177
178 if (!Finished) {
179
180 if (Status == IntWalk_PointConfondu) {
181 StepU = Min(Abs(1.5 * Du),pas*(UM-Um));
182 StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
183
184 Standard_Real d2dx = Abs(previousd2d.X());
185 Standard_Real d2dy = Abs(previousd2d.Y());
186
187 if (d2dx < tolerance(1)) {
188 Step = StepV/d2dy;
189 }
190 else if (d2dy < tolerance(2)) {
191 Step = StepU/d2dx;
192 }
193 else {
194 Step = Min(StepU/d2dx,StepV/d2dy);
195 }
196
197
198
199 }
200 else {
201// on estime la fleche courante.
202// si fleche/2<=flechecourante<= fleche on considere que le critere est
203// respecte.
204// sinon ajuster le pas en fonction du pas precedent
205
206/*
207 Standard_Real Dist = Sqrt(Norme)/3.;
208 TColgp_Array1OfPnt Poles(1,4);
209 gp_Pnt POnCurv,Milieu;
210 Poles(1) = previousPoint.Value();
211 Poles(4) = sp.Point();
212 Poles(2) = Poles(1).XYZ() +
213 StepSign * Dist* previousd3d.Normalized().XYZ();
214 Poles(3) = Poles(4).XYZ() -
215 StepSign * Dist*sp.Direction3d().Normalized().XYZ();
216 BzCLib::PntPole(0.5,Poles,POnCurv);
217 Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
218// FlecheCourante = Milieu.Distance(POnCurv);
219 Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
220*/
221
222 // Calcul direct :
223 // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
224 // soit POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
225 // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
226 // Donc POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
227 // On calcule l'ecart avec (p1+p4)/2. . Il faut donc juste calculer
228 // la norme (au carre) de 3.*lambda (d1 - d4)/8.
229 // soit la norme de :
230 // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
231 // ce qui fait, en prenant le carre :
232 // Norme * (d1-d4).SquareMagnitude()/64.
233
234 Standard_Real FlecheCourante =
235 (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
236
237
238// if (FlecheCourante <= 0.5*fleche) {
239 if (FlecheCourante <= 0.25*fleche*fleche) {
240
241 Standard_Real d2dx = Abs(sp.Direction2d().X());
242 Standard_Real d2dy = Abs(sp.Direction2d().Y());
243
244 StepU = Min(Abs(1.5*Du),pas*(UM-Um));
245 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
246
247 if (d2dx < tolerance(1)) {
248 Step = StepV/d2dy;
249 }
250 else if (d2dy < tolerance(2)) {
251 Step = StepU/d2dx;
252 }
253 else {
254 Step = Min(StepU/d2dx,StepV/d2dy);
255 }
256
257 }
258 else {
259// if (FlecheCourante > fleche) { // pas trop grand
260 if (FlecheCourante > fleche*fleche) { // pas trop grand
261 Step = Step /2.;
262 Status = IntWalk_PasTropGrand;
263 }
264 else {
265 Standard_Real d2dx = Abs(sp.Direction2d().X());
266 Standard_Real d2dy = Abs(sp.Direction2d().Y());
267
268 StepU = Min(Abs(1.5*Du),pas*(UM-Um));
269 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
270
271 if (d2dx < tolerance(1)) {
272 Step = Min(Step,StepV/d2dy);
273 }
274 else if (d2dy < tolerance(2)) {
275 Step = Min(Step,StepU/d2dx);
276 }
277 else {
278 Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
279 }
280 }
281 }
282 }
283 }
284 return Status;
285}
286
287
288
289