0023952: Improving thread-safety of intersections, approximations and other modeling...
[occt.git] / src / IntWalk / IntWalk_PWalking_3.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
7fd59977 19#include <Standard_Failure.hxx>
20#include <Precision.hxx>
21
22//#define DEBUG 0
23
1ef32e96
RL
24namespace {
25//OCC431(apo): modified ->
26static const Standard_Real CosRef2D = Cos(M_PI/9.0), AngRef2D = M_PI/2.0;
27
28static const Standard_Real d = 7.0;
29}
30
b311480e 31IntWalk_StatusDeflection IntWalk_PWalking::TestDeflection()
7fd59977 32
33// tester si fleche respectee en calculant un majorant de fleche
34// soit le point precedent et sa tangente ,le point nouveau calcule et sa
35// tangente ;on peut trouver une cubique passant par ces 2 points et ayant
36// pour derivee les tangentes de l intersection
37// calculer le point au parametre 0.5 sur la cubique=p1
38// calculer le point milieu des 2 points d intersection=p2
39// si fleche/2<=||p1p2||<= fleche on considere que l on respecte la fleche
40// sinon ajuster le pas en fonction du rapport ||p1p2||/fleche et du pas
41// precedent
42// tester si dans les 2 plans tangents des surfaces on a pas un angle2d trop
43// grand : si oui diviser le pas
44// tester s il n y a pas changement de rive
45//
46{
7fd59977 47 if(line->NbPoints() ==1 ) {
48 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND=STATIC_PRECEDENT_INFLEXION=0;
49 }
50
51 IntWalk_StatusDeflection Status = IntWalk_OK;
52 Standard_Real FlecheCourante ,Ratio;
53
54
55 const IntSurf_PntOn2S& CurrentPoint = myIntersectionOn2S.Point();
56 //==================================================================================
57 //========= A r r e t s u r p o i n t ============
58 //==================================================================================
59 if (myIntersectionOn2S.IsTangent()) {
60 return IntWalk_ArretSurPoint;
61 }
62
63 const gp_Dir& TgCourante = myIntersectionOn2S.Direction();
64
65 //==================================================================================
66 //========= R i s q u e d e p o i n t d i n f l e x i o n ============
67 //==================================================================================
68 if (TgCourante.Dot(previousd)<0) {
69 //------------------------------------------------------------
70 //-- Risque de point d inflexion : On divise le pas par 2
71 //-- On initialise STATIC_PRECEDENT_INFLEXION pour qu a
72 //-- l appel suivant, on retourne Pas_OK si il n y a
73 //-- plus de risque de point d inflexion
74 //------------------------------------------------------------
75
76 pasuv[0]*=0.5;
77 pasuv[1]*=0.5;
78 pasuv[2]*=0.5;
79 pasuv[3]*=0.5;
80 STATIC_PRECEDENT_INFLEXION+=3;
81 if (pasuv[0] < ResoU1 && pasuv[1] <ResoV1 && pasuv[2] <ResoU2 && pasuv[3] < ResoV2)
82 return IntWalk_ArretSurPointPrecedent;
83 else
84 return IntWalk_PasTropGrand;
85 }
86
87 else {
88 if(STATIC_PRECEDENT_INFLEXION > 0) {
89 STATIC_PRECEDENT_INFLEXION -- ;
90 return IntWalk_OK;
91 }
92 }
93
94 //==================================================================================
95 //========= D e t e c t i o n d e P o in t s c o n f o n d u s ===========
96 //==================================================================================
97
98 Standard_Real Dist = previousPoint.Value().
99 SquareDistance(CurrentPoint.Value());
100
101
102 if (Dist < tolconf*tolconf ) {
103 pasuv[0] = Max(5.*ResoU1,Min(1.5*pasuv[0],pasInit[0]));
104 pasuv[1] = Max(5.*ResoV1,Min(1.5*pasuv[1],pasInit[1]));
105 pasuv[2] = Max(5.*ResoU2,Min(1.5*pasuv[2],pasInit[2]));
106 pasuv[3] = Max(5.*ResoV2,Min(1.5*pasuv[3],pasInit[3]));
107 Status = IntWalk_PointConfondu;
108 }
109
110 //==================================================================================
111 Standard_Real Up1,Vp1,Uc1,Vc1,Du1,Dv1,AbsDu1,AbsDu2,AbsDv1,AbsDv2;
112 Standard_Real Up2,Vp2,Uc2,Vc2,Du2,Dv2;
113
114 previousPoint.Parameters(Up1,Vp1,Up2,Vp2);
115 CurrentPoint.Parameters(Uc1,Vc1,Uc2,Vc2);
116
117 Du1 = Uc1 - Up1; Dv1 = Vc1 - Vp1;
118 Du2 = Uc2 - Up2; Dv2 = Vc2 - Vp2;
119
120 AbsDu1 = Abs(Du1);
121 AbsDu2 = Abs(Du2);
122 AbsDv1 = Abs(Dv1);
123 AbsDv2 = Abs(Dv2);
124 //=================================================================================
125 //==== P a s d e p r o g r e s s i o n (entre previous et Current) =======
126 //=================================================================================
127 if ( AbsDu1 < ResoU1 && AbsDv1 < ResoV1
128 && AbsDu2 < ResoU2 && AbsDv2 < ResoV2) {
129 pasuv[0] = ResoU1; pasuv[1] = ResoV1; pasuv[2] = ResoU2; pasuv[3] = ResoV2;
130 return(IntWalk_ArretSurPointPrecedent);
131 }
132 //==================================================================================
1ef32e96 133
7fd59977 134 Standard_Real tolArea = 100.0;
135 if (ResoU1 < Precision::PConfusion() ||
136 ResoV1 < Precision::PConfusion() ||
137 ResoU2 < Precision::PConfusion() ||
138 ResoV2 < Precision::PConfusion() )
139 tolArea = tolArea*2.0;
140
141 Standard_Real Cosi1, CosRef1, Ang1, AngRef1, ResoUV1, Duv1, d1, tolCoeff1;
142 Standard_Real Cosi2, CosRef2, Ang2, AngRef2, ResoUV2, Duv2, d2, tolCoeff2;
143 Cosi1 = Du1*previousd1.X() + Dv1*previousd1.Y();
144 Cosi2 = Du2*previousd2.X() + Dv2*previousd2.Y();
145 Duv1 = Du1*Du1 + Dv1*Dv1;
146 Duv2 = Du2*Du2 + Dv2*Dv2;
147 ResoUV1 = ResoU1*ResoU1 + ResoV1*ResoV1;
148 ResoUV2 = ResoU2*ResoU2 + ResoV2*ResoV2;
149 //
150 //modified by NIZNHY-PKV Wed Nov 13 12:25:44 2002 f
151 //
152 Standard_Real aMinDiv2=Precision::Confusion();
153 aMinDiv2=aMinDiv2*aMinDiv2;
154 //
155 d1=d;
156 if (Duv1>aMinDiv2) {
157 d1 = Abs(ResoUV1/Duv1);
158 d1 = Min(Sqrt(d1)*tolArea, d);
159 }
160 //d1 = Abs(ResoUV1/Duv1);
161 //d1 = Min(Sqrt(d1)*tolArea,d);
162 //modified by NIZNHY-PKV Wed Nov 13 12:34:30 2002 t
163 tolCoeff1 = Exp(d1);
164 //
165 //modified by NIZNHY-PKV Wed Nov 13 12:34:43 2002 f
166 d2=d;
167 if (Duv2>aMinDiv2) {
168 d2 = Abs(ResoUV2/Duv2);
169 d2 = Min(Sqrt(d2)*tolArea,d);
170 }
171 //d2 = Abs(ResoUV2/Duv2);
172 //d2 = Min(Sqrt(d2)*tolArea,d);
173 //modified by NIZNHY-PKV Wed Nov 13 12:34:53 2002 t
174 tolCoeff2 = Exp(d2);
175 CosRef1 = CosRef2D/tolCoeff1;
176 CosRef2 = CosRef2D/tolCoeff2;
177 //
178 //==================================================================================
179 //== Les points ne sont pas confondus : ==
180 //== D e t e c t i o n d e A r r e t s u r P o i n t p r e c e d e n t ==
181 //== P a s T r o p G r a n d (angle dans Esp UV) ==
182 //== C h a n g e m e n t d e r i v e ==
183 //==================================================================================
184 if (Status != IntWalk_PointConfondu) {
185 if(Cosi1*Cosi1 < CosRef1*Duv1 || Cosi2*Cosi2 < CosRef2*Duv2) {
186 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
187 if (pasuv[0]<ResoU1 && pasuv[1]<ResoV1 && pasuv[2]<ResoU2 && pasuv[3]<ResoV2) {
188 return(IntWalk_ArretSurPointPrecedent);
189 }
190 else {
191 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
192 return(IntWalk_PasTropGrand);
193 }
194 }
195 const gp_Dir2d& Tg2dcourante1 = myIntersectionOn2S.DirectionOnS1();
196 const gp_Dir2d& Tg2dcourante2 = myIntersectionOn2S.DirectionOnS2();
197 Cosi1 = Du1*Tg2dcourante1.X() + Dv1*Tg2dcourante1.Y();
198 Cosi2 = Du2*Tg2dcourante2.X() + Dv2*Tg2dcourante2.Y();
199 Ang1 = Abs(previousd1.Angle(Tg2dcourante1));
200 Ang2 = Abs(previousd2.Angle(Tg2dcourante2));
201 AngRef1 = AngRef2D*tolCoeff1;
202 AngRef2 = AngRef2D*tolCoeff2;
203 //-------------------------------------------------------
204 //-- Test : Angle trop grand dans l espace UV -----
205 //-- Changement de rive -----
206 //-------------------------------------------------------
207 if(Cosi1*Cosi1 < CosRef1*Duv1 || Cosi2*Cosi2 < CosRef2*Duv2 || Ang1 > AngRef1 || Ang2 > AngRef2) {
208 pasuv[0]*=0.5; pasuv[1]*=0.5; pasuv[2]*=0.5; pasuv[3]*=0.5;
209 if (pasuv[0]<ResoU1 && pasuv[1]<ResoV1 && pasuv[2]<ResoU2 && pasuv[3]<ResoV2)
210 return(IntWalk_ArretSurPoint);
211 else
212 return(IntWalk_PasTropGrand);
213 }
214 }
215 //<-OCC431(apo)
216 //==================================================================================
217 //== D e t e c t i o n d e : Pas Trop Petit
218 //== Pas Trop Grand
219 //==================================================================================
220
221 //---------------------------------------
222 //-- Estimation de la fleche --
223 //---------------------------------------
224 FlecheCourante =
225 Sqrt(Abs((previousd.XYZ()-TgCourante.XYZ()).SquareModulus()*Dist))/8.;
226
227 if ( FlecheCourante<= fleche*0.5) { //-- Pas Courant trop petit
228 if(FlecheCourante>1e-16) {
229 Ratio = 0.5*(fleche/FlecheCourante);
230 }
231 else {
232 Ratio = 10.0;
233 }
234 Standard_Real pasSu1 = pasuv[0];
235 Standard_Real pasSv1 = pasuv[1];
236 Standard_Real pasSu2 = pasuv[2];
237 Standard_Real pasSv2 = pasuv[3];
238
239 //-- Dans les cas ou lorsqu on demande
240 //-- un point a U+DeltaU , ....
241 //-- on recupere un point a U + Epsilon
242 //-- Epsilon << DeltaU.
243
244 if(pasuv[0]< AbsDu1) pasuv[0] = AbsDu1;
245 if(pasuv[1]< AbsDv1) pasuv[1] = AbsDv1;
246 if(pasuv[2]< AbsDu2) pasuv[2] = AbsDu2;
247 if(pasuv[3]< AbsDv2) pasuv[3] = AbsDv2;
248
249 if(pasuv[0]<ResoU1) pasuv[0]=ResoU1;
250 if(pasuv[1]<ResoV1) pasuv[1]=ResoV1;
251 if(pasuv[2]<ResoU2) pasuv[2]=ResoU2;
252 if(pasuv[3]<ResoV2) pasuv[3]=ResoV2;
253 //-- if(Ratio>10.0 ) { Ratio=10.0; }
254 Standard_Real R1,R = pasInit[0]/pasuv[0];
255 R1= pasInit[1]/pasuv[1]; if(R1<R) R=R1;
256 R1= pasInit[2]/pasuv[2]; if(R1<R) R=R1;
257 R1= pasInit[3]/pasuv[3]; if(R1<R) R=R1;
258 if(Ratio > R) Ratio=R;
259 pasuv[0] = Min(Ratio*pasuv[0],pasInit[0]);
260 pasuv[1] = Min(Ratio*pasuv[1],pasInit[1]);
261 pasuv[2] = Min(Ratio*pasuv[2],pasInit[2]);
262 pasuv[3] = Min(Ratio*pasuv[3],pasInit[3]);
263 if (pasuv[0] != pasSu1 || pasuv[2] != pasSu2||
264 pasuv[1] != pasSv1 || pasuv[3] != pasSv2) {
265 if(++STATIC_BLOCAGE_SUR_PAS_TROP_GRAND > 5) {
266 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND = 0;
267 return IntWalk_PasTropGrand;
268 }
269 }
270 if(Status == IntWalk_OK) {
271 STATIC_BLOCAGE_SUR_PAS_TROP_GRAND=0;
272 //-- On tente d augmenter le pas
273 }
274 return Status;
275 }
276 else { //-- FlecheCourante > fleche*0.5
277 if (FlecheCourante > fleche) { //-- Pas Courant Trop Grand
278 Ratio = fleche/FlecheCourante;
279 pasuv[0] = Ratio*pasuv[0];
280 pasuv[1] = Ratio*pasuv[1];
281 pasuv[2] = Ratio*pasuv[2];
282 pasuv[3] = Ratio*pasuv[3];
283 //if(++STATIC_BLOCAGE_SUR_PAS_TROP_GRAND > 5) {
284 // STATIC_BLOCAGE_SUR_PAS_TROP_GRAND = 0;
285 return IntWalk_PasTropGrand;
286 //}
287 }
288 else { //-- fleche/2 < FlecheCourante <= fleche
289 Ratio = 0.75 * (fleche / FlecheCourante);
290 }
291 }
292 pasuv[0] = Max(5.*ResoU1,Min(Min(Ratio*AbsDu1,pasuv[0]),pasInit[0]));
293 pasuv[1] = Max(5.*ResoV1,Min(Min(Ratio*AbsDv1,pasuv[1]),pasInit[1]));
294 pasuv[2] = Max(5.*ResoU2,Min(Min(Ratio*AbsDu2,pasuv[2]),pasInit[2]));
295 pasuv[3] = Max(5.*ResoV2,Min(Min(Ratio*AbsDv2,pasuv[3]),pasInit[3]));
296 if(Status == IntWalk_OK) STATIC_BLOCAGE_SUR_PAS_TROP_GRAND=0;
297 return Status;
298}
299
300
301