0024360: Hang up trying to intersect two faces
[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 19namespace {
b1c5c4e6 20 static const Standard_Real CosRef3D = 0.98;// rule by tests in U4
21 // correspond to 11.478 d
22 static const Standard_Real CosRef2D = 0.88; // correspond to 25 d
23 static const Standard_Integer MaxDivision = 60; // max number of step division
24 // because the angle is too great in 2d (U4)
1ef32e96
RL
25}
26
7fd59977 27IntWalk_StatusDeflection IntWalk_IWalking::TestDeflection
28 (TheIWFunction& sp,
29 const Standard_Boolean Finished,
30 const math_Vector& UV,
31 const IntWalk_StatusDeflection StatusPrecedent,
32 Standard_Integer& NbDivision,
33 Standard_Real& Step,
34 const Standard_Integer StepSign)
35{
b1c5c4e6 36 // Check the step of advancement, AND recalculate this step :
7fd59977 37 //
b1c5c4e6 38 // 1) test point confused
39 // if yes other tests are not done
40 // 2) test angle 3d too great
41 // if yes divide the step and leave
42 // angle3d = angle ((previous point, calculated point),
43 // previous tangent)
44 // 3) check step of advancement in 2d
45 // 4) test point confused
46 // 5) test angle 2d too great
47 // 6) test point of tangency
48 // if yes leave
49 // 7) calculate the tangent by u,v of the section
50 // 8) test angle 3d too great
51 // angle3d = angle ((previous point, calculated point),
52 // new tangent)
53 // 9) test angle 2d too great
54 //10) test change of side (pass the tangent point not knowing it)
55 //11) calculate the step of advancement depending on the vector
56 //12) adjust the step depending on the previous steps
7fd59977 57
58 IntWalk_StatusDeflection Status = IntWalk_OK;
59
7fd59977 60 //---------------------------------------------------------------------------------
b1c5c4e6 61 //-- lbr le 4 Avril 95 : it is possible that the status returns points confused
62 //-- if epsilon is great enough (1e-11). In this case one loops
63 //-- without ever changing the values sent to Rsnld.
7fd59977 64 //---------------------------------------------------------------------------------
65 Standard_Real Paramu, Paramv, StepU,StepV;
66 Standard_Real Cosi, Cosi2, Norme;
67
68 gp_Vec Corde(previousPoint.Value(), sp.Point());
69
70 Norme = Corde.SquareMagnitude();
71// if (Norme <= epsilon*epsilon) {
b1c5c4e6 72 if ((++NbPointsConfondusConsecutifs < 10) && (Norme <= epsilon)) { // the square is already taken in the constructor
7fd59977 73 Status = IntWalk_PointConfondu;
74 if (StatusPrecedent == IntWalk_PasTropGrand) {
75 return IntWalk_ArretSurPointPrecedent;
76 }
77
b1c5c4e6 78 if(++EpsilonSembleTropGrand > 5 && NbPointsConfondusConsecutifs == 8) { //-- Temporary
79 if(epsilon>0.00000000001) epsilon*=0.5; //-- Temporary
80 EpsilonSembleTropGrand = 0; //-- Temporary
7fd59977 81 }
82 }
83 else {
b1c5c4e6 84 NbPointsConfondusConsecutifs = 0; //-- Temporary
85 EpsilonSembleTropGrand = 0; //-- Temporary
86 if(Norme<1e-16) Norme = 1e-16; //-- Temporary
7fd59977 87
88 Cosi = Corde * previousd3d;
89 if (Cosi*StepSign < 0.) { // angle 3d > pi/2 !!!!
90 Cosi2 = 0.;
91 }
92 else {
93 Cosi2 = Cosi * Cosi / previousd3d.SquareMagnitude() / Norme;
94 }
b1c5c4e6 95 if (Cosi2 < CosRef3D) { //angle 3d too great
7fd59977 96 Step = Step /2.0;
97 StepU = Abs(Step*previousd2d.X());
98 StepV = Abs(Step*previousd2d.Y());
99 if (StepU < tolerance(1) && StepV < tolerance(2))
100 Status = IntWalk_ArretSurPointPrecedent;
101 else
102 Status = IntWalk_PasTropGrand;
103 return Status;
104 }
105 }
106
107 if (!reversed) {
108 previousPoint.ParametersOnS2(Paramu, Paramv);
109 }
110 else {
111 previousPoint.ParametersOnS1(Paramu, Paramv);
112 }
113 Standard_Real Du = UV(1) - Paramu;
114 Standard_Real Dv = UV(2) - Paramv;
115 Standard_Real Duv = Du * Du + Dv * Dv;
116 if (Abs(Du) < tolerance(1) && Abs(Dv) < tolerance(2))
b1c5c4e6 117 return IntWalk_ArretSurPointPrecedent; //confused point 2d
7fd59977 118 Cosi = StepSign * (Du * previousd2d.X() +
119 Dv * previousd2d.Y());
120 if (Cosi < 0 && Status == IntWalk_PointConfondu)
b1c5c4e6 121 return IntWalk_ArretSurPointPrecedent; // leave as step back
122 // with confused point
7fd59977 123
124
125 if (sp.IsTangent())
126 return IntWalk_ArretSurPoint;
127
b1c5c4e6 128//if during routing one has subdivided more than MaxDivision for each
129//previous step, bug on the square; do nothing (experience U4)
7fd59977 130
131 if (NbDivision < MaxDivision &&
132 Status != IntWalk_PointConfondu &&
133 StatusPrecedent!= IntWalk_PointConfondu ) {
134 Cosi2 = Cosi * Cosi / Duv;
135 if (Cosi2 < CosRef2D || Cosi < 0 ) {
136 Step = Step / 2.0;
137 StepU = Abs(Step*previousd2d.X());
138 StepV = Abs(Step*previousd2d.Y());
139
140 if (StepU < tolerance(1) && StepV < tolerance(2))
141 Status = IntWalk_ArretSurPointPrecedent;
142 else
143 Status = IntWalk_PasTropGrand;
144 NbDivision = NbDivision + 1;
145 return Status;
146 }
147
148 Cosi = Corde * sp.Direction3d();
149 Cosi2 = Cosi * Cosi / sp.Direction3d().SquareMagnitude() / Norme;
b1c5c4e6 150 if (Cosi2 < CosRef3D ){ //angle 3d too great
7fd59977 151 Step = Step / 2.;
152 StepU = Abs(Step*previousd2d.X());
153 StepV = Abs(Step*previousd2d.Y());
154 if (StepU < tolerance(1) && StepV < tolerance(2))
155 Status = IntWalk_ArretSurPoint;
156 else
157 Status = IntWalk_PasTropGrand;
158 return Status;
159 }
160 Cosi = Du * sp.Direction2d().X() +
161 Dv * sp.Direction2d().Y();
162 Cosi2 = Cosi * Cosi / Duv;
163 if (Cosi2 < CosRef2D ||
164 sp.Direction2d() * previousd2d < 0) {
b1c5c4e6 165 //angle 2d too great or change the side
7fd59977 166 Step = Step / 2.;
167 StepU = Abs(Step*previousd2d.X());
168 StepV = Abs(Step*previousd2d.Y());
169 if (StepU < tolerance(1) && StepV < tolerance(2))
170 Status = IntWalk_ArretSurPointPrecedent;
171 else
172 Status = IntWalk_PasTropGrand;
173 return Status;
174 }
175 }
176
177 if (!Finished) {
178
179 if (Status == IntWalk_PointConfondu) {
180 StepU = Min(Abs(1.5 * Du),pas*(UM-Um));
181 StepV = Min(Abs(1.5 * Dv),pas*(VM-Vm));
182
183 Standard_Real d2dx = Abs(previousd2d.X());
184 Standard_Real d2dy = Abs(previousd2d.Y());
185
186 if (d2dx < tolerance(1)) {
187 Step = StepV/d2dy;
188 }
189 else if (d2dy < tolerance(2)) {
190 Step = StepU/d2dx;
191 }
192 else {
193 Step = Min(StepU/d2dx,StepV/d2dy);
194 }
195
196
197
198 }
199 else {
b1c5c4e6 200// estimate the current vector.
201// if vector/2<=current vector<= vector it is considered that the criterion
202// is observed.
203// otherwise adjust the step depending on the previous step
7fd59977 204
205/*
206 Standard_Real Dist = Sqrt(Norme)/3.;
207 TColgp_Array1OfPnt Poles(1,4);
208 gp_Pnt POnCurv,Milieu;
209 Poles(1) = previousPoint.Value();
210 Poles(4) = sp.Point();
211 Poles(2) = Poles(1).XYZ() +
212 StepSign * Dist* previousd3d.Normalized().XYZ();
213 Poles(3) = Poles(4).XYZ() -
214 StepSign * Dist*sp.Direction3d().Normalized().XYZ();
215 BzCLib::PntPole(0.5,Poles,POnCurv);
216 Milieu = (Poles(1).XYZ() + Poles(4).XYZ())*0.5;
217// FlecheCourante = Milieu.Distance(POnCurv);
218 Standard_Real FlecheCourante = Milieu.SquareDistance(POnCurv);
219*/
220
b1c5c4e6 221 // Direct calculation :
7fd59977 222 // POnCurv=(((p1+p2)/2.+(p2+p3)/2.)/2. + ((p2+p3)/2.+(p3+P4)/2.)/2.)/2.
b1c5c4e6 223 // either POnCurv = p1/8. + 3.p2/8. + 3.p3/8. + p4/8.
7fd59977 224 // Or p2 = p1 + lambda*d1 et p3 = p4 - lambda*d4
b1c5c4e6 225 // So POnCurv = (p1 + p4)/2. + 3.*(lambda d1 - lambda d4)/8.
226 // Calculate the deviation with (p1+p4)/2. . So it is just necessary to calculate
227 // the norm (square) of 3.*lambda (d1 - d4)/8.
228 // either the norm of :
7fd59977 229 // 3.*(Sqrt(Norme)/3.)*StepSign*(d1-d4)/8.
b1c5c4e6 230 // which produces, takin the square :
7fd59977 231 // Norme * (d1-d4).SquareMagnitude()/64.
232
233 Standard_Real FlecheCourante =
234 (previousd3d.Normalized().XYZ()-sp.Direction3d().Normalized().XYZ()).SquareModulus()*Norme/64.;
235
236
237// if (FlecheCourante <= 0.5*fleche) {
238 if (FlecheCourante <= 0.25*fleche*fleche) {
239
240 Standard_Real d2dx = Abs(sp.Direction2d().X());
241 Standard_Real d2dy = Abs(sp.Direction2d().Y());
242
243 StepU = Min(Abs(1.5*Du),pas*(UM-Um));
244 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
245
246 if (d2dx < tolerance(1)) {
247 Step = StepV/d2dy;
248 }
249 else if (d2dy < tolerance(2)) {
250 Step = StepU/d2dx;
251 }
252 else {
253 Step = Min(StepU/d2dx,StepV/d2dy);
254 }
255
256 }
257 else {
de09d2a2 258// if (FlecheCourante > fleche) { // step too great
259 if (FlecheCourante > fleche*fleche) { // step too great
7fd59977 260 Step = Step /2.;
de09d2a2 261 StepU = Abs(Step*previousd2d.X());
262 StepV = Abs(Step*previousd2d.Y());
263 if (StepU < tolerance(1) && StepV < tolerance(2))
264 Status = IntWalk_ArretSurPointPrecedent;
265 else
266 Status = IntWalk_PasTropGrand;
7fd59977 267 }
268 else {
269 Standard_Real d2dx = Abs(sp.Direction2d().X());
270 Standard_Real d2dy = Abs(sp.Direction2d().Y());
271
272 StepU = Min(Abs(1.5*Du),pas*(UM-Um));
273 StepV = Min(Abs(1.5*Dv),pas*(VM-Vm));
274
275 if (d2dx < tolerance(1)) {
276 Step = Min(Step,StepV/d2dy);
277 }
278 else if (d2dy < tolerance(2)) {
279 Step = Min(Step,StepU/d2dx);
280 }
281 else {
282 Step = Min(Step,Min(StepU/d2dx,StepV/d2dy));
283 }
284 }
285 }
286 }
287 }
288 return Status;
289}
290
291
292
293