b311480e |
1 | // Created on: 1997-03-04 |
2 | // Created by: Prestataire Xuan PHAM PHU |
3 | // Copyright (c) 1995-1999 Matra Datavision |
4 | // Copyright (c) 1999-2012 OPEN CASCADE SAS |
5 | // |
6 | // The content of this file is subject to the Open CASCADE Technology Public |
7 | // License Version 6.5 (the "License"). You may not use the content of this file |
8 | // except in compliance with the License. Please obtain a copy of the License |
9 | // at http://www.opencascade.org and read it completely before using this file. |
10 | // |
11 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
12 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
13 | // |
14 | // The Original Code and all software distributed under the License is |
15 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
16 | // Initial Developer hereby disclaims all such warranties, including without |
17 | // limitation, any warranties of merchantability, fitness for a particular |
18 | // purpose or non-infringement. Please see the License for the specific terms |
19 | // and conditions governing the rights and limitations under the License. |
20 | |
21 | |
7fd59977 |
22 | // Modified: eap Mar 25 2002 (occ102,occ227), touch case |
23 | #include <TopTrans_SurfaceTransition.ixx> |
24 | |
25 | #include <gp_Dir.hxx> |
26 | #include <TopAbs.hxx> |
27 | #include <TopAbs_State.hxx> |
28 | #include <TopAbs_Orientation.hxx> |
29 | #include <Precision.hxx> |
30 | |
31 | #define Msr Standard_Real |
32 | #define Msi Standard_Integer |
33 | #define Msb Standard_Boolean |
34 | #define Msf Standard_False |
35 | #define Mst Standard_True |
36 | #define MTAo TopAbs_Orientation |
37 | #define MTAs TopAbs_State |
38 | |
39 | static Standard_Boolean STATIC_DEFINED = Standard_False; |
40 | |
41 | //#include <TopOpeBRepTool_EXPORT.hxx> |
42 | static gp_Dir FUN_nCinsideS(const gp_Dir& tgC, const gp_Dir& ngS) |
43 | { |
44 | // Give us a curve C on suface S, <parOnC>, a parameter |
45 | // Purpose : compute normal vector to C, tangent to S at |
46 | // given point , oriented INSIDE S |
47 | // <tgC> : geometric tangent at point of <parOnC> |
48 | // <ngS> : geometric normal at point of <parOnC> |
49 | gp_Dir XX(ngS^tgC); |
50 | return XX; |
51 | } |
52 | |
53 | #define M_REVERSED(st) (st == TopAbs_REVERSED) |
54 | #define M_INTERNAL(st) (st == TopAbs_INTERNAL) |
55 | #define M_UNKNOWN(st) (st == TopAbs_UNKNOWN) |
56 | |
57 | static Standard_Integer FUN_OO(const Standard_Integer i) |
58 | { |
59 | if (i == 1) return 2; |
60 | if (i == 2) return 1; |
61 | return 0; |
62 | } |
63 | |
64 | //static Standard_Real FUN_Ang(const gp_Dir& Normref, |
65 | static Standard_Real FUN_Ang(const gp_Dir& , |
66 | const gp_Dir& beafter, |
67 | const gp_Dir& TgC, |
68 | const gp_Dir& Norm, |
69 | const TopAbs_Orientation O) |
70 | { |
71 | gp_Dir dironF = FUN_nCinsideS(TgC,Norm); |
72 | if (M_REVERSED(O)) dironF.Reverse(); |
73 | |
74 | Standard_Real ang = beafter.AngleWithRef(dironF,TgC); |
75 | return ang; |
76 | } |
77 | |
78 | static void FUN_getSTA(const Standard_Real Ang, const Standard_Real tola, |
79 | Standard_Integer& i, Standard_Integer& j) |
80 | { |
81 | Standard_Real cos = Cos(Ang); |
82 | Standard_Real sin = Sin(Ang); |
83 | Standard_Boolean nullcos = Abs(cos) < tola; |
84 | Standard_Boolean nullsin = Abs(sin) < tola; |
85 | if (nullcos) i = 0; |
86 | else i = (cos > 0.) ? 1 : 2; |
87 | if (nullsin) j = 0; |
88 | else j = (sin > 0.) ? 1 : 2; |
89 | } |
90 | |
91 | /*static void FUN_getSTA(const Standard_Real Ang, const Standard_Real tola, |
92 | const Standard_Real Curv, const Standard_Real CurvRef, |
93 | Standard_Integer& i, Standard_Integer& j) |
94 | { |
95 | // Choosing UV referential (beafter,myNorm). |
96 | // purpose : computes position boundary face relative to the reference surface |
97 | // notice : j==0 => j==1 : the boundary face is ABOVE the reference surface |
98 | // j==2 : the boundary face is UNDER the reference surface |
99 | // - j==0 : the boundary and the reference objects are tangent- |
100 | |
101 | FUN_getSTA(Ang,tola,i,j); |
102 | if (j == 0) { |
103 | Standard_Real diff = Curv - CurvRef; |
104 | if (Abs(diff) < tola) {STATIC_DEFINED = Standard_False; return;} // nyi FUN_Raise |
105 | j = (diff < 0.) ? 1 : 2; |
106 | } |
107 | }*/ |
108 | #ifndef DEB |
109 | #define M_Unknown (-100) |
110 | #else |
111 | #define M_Unknown (-100.) |
112 | #endif |
113 | #define M_noupdate (0) |
114 | #define M_updateREF (1) |
115 | #define M_Ointernal (10) |
116 | static Standard_Integer FUN_refnearest(const Standard_Real Angref, const TopAbs_Orientation Oriref, |
117 | const Standard_Real Ang, const TopAbs_Orientation Ori, const Standard_Real tola) |
118 | { |
119 | Standard_Boolean undef = (Angref == 100.); |
120 | if (undef) return M_updateREF; |
121 | |
122 | Standard_Real cosref = Cos(Angref), cos = Cos(Ang); |
123 | Standard_Real dcos = Abs(cosref) - Abs(cos); |
124 | if (Abs(dcos) < tola) { |
125 | // Analysis for tangent cases : if two boundary faces are same sided |
126 | // and have tangent normals, if they have opposite orientations |
127 | // we choose INTERNAL as resulting complex transition (case EXTERNAL |
128 | // refering to no logical case) |
129 | if (TopAbs::Complement(Ori) == Oriref) return M_Ointernal; |
130 | else return (Standard_Integer ) M_Unknown; // nyi FUN_RAISE |
131 | } |
132 | Standard_Integer updateref = (dcos > 0.)? M_noupdate : M_updateREF; |
133 | return updateref; |
134 | } |
135 | |
136 | //======================================================================= |
137 | //function : FUN_refnearest |
138 | //purpose : |
139 | //======================================================================= |
140 | |
141 | static Standard_Integer FUN_refnearest(const Standard_Integer i, |
142 | const Standard_Integer j, |
143 | const Standard_Real CurvSref, |
144 | const Standard_Real Angref, |
145 | const TopAbs_Orientation Oriref, |
146 | const Standard_Real Curvref, |
147 | const Standard_Real Ang, |
148 | const TopAbs_Orientation Ori, |
149 | const Standard_Real Curv, |
150 | const Standard_Real tola, |
151 | Standard_Boolean & TouchFlag) // eap Mar 25 2002 |
152 | { |
153 | Standard_Boolean iisj = (i == j); |
154 | Standard_Real abscos = Abs(Cos(Ang)); |
155 | Standard_Boolean i0 = (Abs(1. - abscos) < tola); |
156 | Standard_Boolean j0 = (abscos < tola); |
157 | Standard_Boolean nullcurv = (Curv == 0.); |
158 | Standard_Boolean curvpos = (Curv > tola); |
159 | Standard_Boolean curvneg = (Curv < -tola); |
160 | Standard_Boolean nullcsref = (CurvSref == 0.); |
161 | |
162 | Standard_Boolean undef = (Angref == 100.); |
163 | if (undef) { |
164 | if (i0) { |
165 | if (iisj && curvneg) return M_noupdate; |
166 | if (!iisj && curvpos) return M_noupdate; |
167 | } |
168 | if (j0) { |
169 | if (!nullcsref && (j == 1) && iisj && (curvpos || nullcurv)) return M_updateREF; |
170 | if (!nullcsref && (j == 1) && !iisj && (curvneg || nullcurv)) return M_updateREF; |
171 | |
172 | if (iisj && curvpos) return M_noupdate; |
173 | if (!iisj && curvneg) return M_noupdate; |
174 | } |
175 | return M_updateREF; |
176 | } // undef |
177 | |
178 | Standard_Real cosref = Cos(Angref), cos = Cos(Ang); |
179 | Standard_Real dcos = Abs(cosref) - Abs(cos); Standard_Boolean samecos = Abs(dcos) < tola; |
180 | if (samecos) { |
181 | // Analysis for tangent cases : if two boundary faces are same sided |
182 | // and have sma dironF. |
183 | |
184 | if (Abs(Curvref - Curv) < 1.e-4) { |
185 | if (TopAbs::Complement(Ori) == Oriref) return M_Ointernal; |
186 | else return (Standard_Integer ) M_Unknown; // nyi FUN_RAISE |
187 | } |
188 | |
189 | Standard_Boolean noupdate = Standard_False; |
190 | if (iisj && (Curvref > Curv)) noupdate = Standard_True; |
191 | if (!iisj && (Curvref < Curv)) noupdate = Standard_True; |
192 | Standard_Integer updateref = noupdate ? M_noupdate : M_updateREF; |
193 | if (!j0) return updateref; |
194 | |
195 | if (!noupdate && !nullcsref) { |
196 | // check for (j==1) the face is ABOVE Sref |
197 | // check for (j==2) the face is BELOW Sref |
198 | if ((j == 2) && (Abs(Curv) < CurvSref)) updateref = M_noupdate; |
199 | if ((j == 1) && (Abs(Curv) > CurvSref)) updateref = M_noupdate; |
200 | } |
201 | return updateref; |
202 | } // samecos |
203 | |
204 | Standard_Integer updateref = (dcos > 0.)? M_noupdate : M_updateREF; |
205 | if (Oriref != Ori) TouchFlag = Standard_True; // eap Mar 25 2002 |
206 | |
207 | return updateref; |
208 | } |
209 | |
210 | // ============================================================ |
211 | // methods |
212 | // ============================================================ |
213 | |
214 | TopTrans_SurfaceTransition::TopTrans_SurfaceTransition() |
215 | : myAng(1,2,1,2),myCurv(1,2,1,2),myOri(1,2,1,2) |
216 | { |
217 | STATIC_DEFINED = Standard_False; |
218 | } |
219 | |
220 | void TopTrans_SurfaceTransition::Reset(const gp_Dir& Tgt, |
221 | const gp_Dir& Norm, |
222 | const gp_Dir& MaxD,const gp_Dir& MinD, |
223 | const Standard_Real MaxCurv,const Standard_Real MinCurv) |
224 | { |
225 | STATIC_DEFINED = Standard_True; |
226 | |
227 | Standard_Real tola = Precision::Angular(); |
228 | Standard_Boolean curismax = (Abs(MaxD.Dot(myTgt)) < tola); |
229 | Standard_Boolean curismin = (Abs(MinD.Dot(myTgt)) < tola); |
230 | |
231 | if ((Abs(MaxCurv) < tola) && (Abs(MinCurv) < tola)) { |
232 | Reset(Tgt,Norm); |
233 | return; |
234 | } |
235 | |
236 | if (!curismax && !curismin) { |
237 | // In the plane normal to <myTgt>, we see the boundary face as |
238 | // a boundary curve. |
239 | // NYIxpu : compute the curvature of the curve if not MaxCurv |
240 | // nor MinCurv. |
241 | |
242 | STATIC_DEFINED = Standard_False; |
243 | return; |
244 | } |
245 | |
246 | if (curismax) myCurvRef = Abs(MaxCurv); |
247 | if (curismin) myCurvRef = Abs(MinCurv); |
248 | if (myCurvRef < tola) myCurvRef = 0.; |
249 | |
250 | // ============================================================ |
251 | // recall : <Norm> is oriented OUTSIDE the "geometric matter" described |
252 | // by the surface |
253 | // - if (myCurvRef != 0.) Sref is UNDER axis (sin = 0) |
254 | // referential (beafter,myNorm,myTgt) - |
255 | // ============================================================ |
256 | |
257 | // beafter oriented (before, after) the intersection on the reference surface. |
258 | myNorm = Norm; |
259 | myTgt = Tgt; |
260 | beafter = Norm^Tgt; |
261 | for (Standard_Integer i = 1; i <=2; i++) |
262 | for (Standard_Integer j = 1; j <=2; j++) |
263 | myAng(i,j) = 100.; |
264 | |
265 | myTouchFlag = Standard_False; // eap Mar 25 2002 |
266 | } |
267 | |
268 | void TopTrans_SurfaceTransition::Reset(const gp_Dir& Tgt, |
269 | const gp_Dir& Norm) |
270 | { |
271 | STATIC_DEFINED = Standard_True; |
272 | |
273 | // beafter oriented (before, after) the intersection on the reference surface. |
274 | myNorm = Norm; |
275 | myTgt = Tgt; |
276 | beafter = Norm^Tgt; |
277 | for (Standard_Integer i = 1; i <=2; i++) |
278 | for (Standard_Integer j = 1; j <=2; j++) |
279 | myAng(i,j) = 100.; |
280 | |
281 | myCurvRef = 0.; |
282 | myTouchFlag = Standard_False; // eap Mar 25 2002 |
283 | } |
284 | |
285 | void TopTrans_SurfaceTransition::Compare |
286 | //(const Standard_Real Tole, |
287 | (const Standard_Real , |
288 | const gp_Dir& Norm, |
289 | const gp_Dir& MaxD,const gp_Dir& MinD, |
290 | const Standard_Real MaxCurv,const Standard_Real MinCurv, |
291 | const TopAbs_Orientation S, |
292 | const TopAbs_Orientation O) |
293 | { |
294 | if (!STATIC_DEFINED) return; |
295 | |
296 | Standard_Real Curv=0.; |
297 | // ------ |
298 | Standard_Real tola = Precision::Angular(); |
299 | Standard_Boolean curismax = (Abs(MaxD.Dot(myTgt)) < tola); |
300 | Standard_Boolean curismin = (Abs(MinD.Dot(myTgt)) < tola); |
301 | if (!curismax && !curismin) { |
302 | // In the plane normal to <myTgt>, we see the boundary face as |
303 | // a boundary curve. |
304 | // NYIxpu : compute the curvature of the curve if not MaxCurv |
305 | // nor MinCurv. |
306 | |
307 | STATIC_DEFINED = Standard_False; |
308 | return; |
309 | } |
310 | if (curismax) Curv = Abs(MaxCurv); |
311 | if (curismin) Curv = Abs(MinCurv); |
312 | if (myCurvRef < tola) Curv = 0.; |
313 | gp_Dir dironF = FUN_nCinsideS(myTgt,Norm); |
314 | Standard_Real prod = (dironF^Norm).Dot(myTgt); |
315 | if (prod < 0.) Curv = -Curv; |
316 | |
317 | Standard_Real Ang; |
318 | // ----- |
319 | Ang = ::FUN_Ang(myNorm,beafter,myTgt,Norm,O); |
320 | |
321 | Standard_Integer i,j; |
322 | // ----- |
323 | // i = 0,1,2 : cos = 0,>0,<0 |
324 | // j = 0,1,2 : sin = 0,>0,<0 |
325 | ::FUN_getSTA(Ang,tola,i,j); |
326 | |
327 | // update nearest : |
328 | // --------------- |
329 | Standard_Integer kmax = M_INTERNAL(O) ? 2 : 1; |
330 | for (Standard_Integer k=1; k <=kmax; k++) { |
331 | if (k == 2) { |
332 | // get the opposite Ang |
333 | i = ::FUN_OO(i); |
334 | j = ::FUN_OO(j); |
335 | } |
336 | Standard_Boolean i0 = (i == 0), j0 = (j == 0); |
337 | Standard_Integer nmax = (i0 || j0) ? 2 : 1; |
338 | for (Standard_Integer n=1; n<=nmax; n++) { |
339 | if (i0) i = n; |
340 | if (j0) j = n; |
341 | |
342 | // if (curvref == 0.) : |
343 | // Standard_Boolean iisj = (i == j); |
344 | // Standard_Boolean Curvpos = (Curv > 0.); |
345 | // if ((Curv != 0.) && i0) { |
346 | // if (iisj && !Curvpos) continue; |
347 | // if (!iisj && Curvpos) continue; |
348 | // } |
349 | // if ((Curv != 0.) && j0) { |
350 | // if (iisj && Curvpos) continue; |
351 | // if (!iisj && !Curvpos) continue; |
352 | // } |
353 | |
354 | Standard_Integer refn = ::FUN_refnearest(i,j,myCurvRef,myAng(i,j),myOri(i,j),myCurv(i,j), |
355 | Ang,/*O*/S,Curv,tola,myTouchFlag); // eap Mar 25 2002 |
356 | if (refn == M_Unknown) {STATIC_DEFINED = Standard_False; return;} |
357 | if (refn > 0) { |
358 | myAng(i,j) = Ang; |
359 | myOri(i,j) = (refn == M_Ointernal) ? TopAbs_INTERNAL : S; |
360 | myCurv(i,j) = Curv; |
361 | } |
362 | } // n=1..nmax |
363 | } // k=1..kmax |
364 | |
365 | } |
366 | |
367 | void TopTrans_SurfaceTransition::Compare |
368 | //(const Standard_Real Tole, |
369 | (const Standard_Real , |
370 | const gp_Dir& Norm, |
371 | const TopAbs_Orientation S, |
372 | const TopAbs_Orientation O) |
373 | { |
374 | if (!STATIC_DEFINED) return; |
375 | |
376 | // oriented Ang(beafter,dironF), |
377 | // dironF normal to the curve, oriented INSIDE F, the added oriented support |
378 | Standard_Real Ang = ::FUN_Ang(myNorm,beafter,myTgt,Norm,O); |
379 | Standard_Real tola = Precision::Angular(); // nyi in arg |
380 | |
381 | // i = 0,1,2 : cos = 0,>0,<0 |
382 | // j = 0,1,2 : sin = 0,>0,<0 |
383 | Standard_Integer i,j; ::FUN_getSTA(Ang,tola,i,j); |
384 | |
385 | Standard_Integer kmax = M_INTERNAL(O) ? 2 : 1; |
386 | for (Standard_Integer k=1; k <=kmax; k++) { |
387 | if (k == 2) { |
388 | // get the opposite Ang |
389 | i = ::FUN_OO(i); |
390 | j = ::FUN_OO(j); |
391 | } |
392 | |
393 | Standard_Boolean i0 = (i == 0), j0 = (j == 0); |
394 | Standard_Integer nmax = (i0 || j0) ? 2 : 1; |
395 | for (Standard_Integer n=1; n<=nmax; n++) { |
396 | if (i0) i = n; |
397 | if (j0) j = n; |
398 | |
399 | Standard_Integer refn = ::FUN_refnearest(myAng(i,j),myOri(i,j), |
400 | Ang,/*O*/S,tola); // eap |
401 | if (refn == M_Unknown) {STATIC_DEFINED = Standard_False; return;} |
402 | |
403 | if (refn > 0) { |
404 | myAng(i,j) = Ang; |
405 | myOri(i,j) = (refn == M_Ointernal) ? TopAbs_INTERNAL : S; |
406 | } |
407 | } // n=1..nmax |
408 | } // k=1..kmax |
409 | } |
410 | |
411 | #define BEFORE (2) |
412 | #define AFTER (1) |
413 | static TopAbs_State FUN_getstate(const TColStd_Array2OfReal& Ang, |
414 | const TopTrans_Array2OfOrientation& Ori, |
415 | const Standard_Integer iSTA, |
416 | const Standard_Integer iINDEX) |
417 | { |
418 | if (!STATIC_DEFINED) return TopAbs_UNKNOWN; |
419 | |
420 | Standard_Real a1 = Ang(iSTA,1), a2 = Ang(iSTA,2); |
421 | Standard_Boolean undef1 = (a1 == 100.), undef2 = (a2 == 100.); |
422 | Standard_Boolean undef = undef1 && undef2; |
423 | if (undef) return TopAbs_UNKNOWN; |
424 | |
425 | if (undef1 || undef2) { |
426 | Standard_Integer jok = undef1 ? 2 : 1; |
427 | TopAbs_Orientation o = Ori(iSTA,jok); |
428 | TopAbs_State st = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o) : |
429 | TopTrans_SurfaceTransition::GetAfter(o); |
430 | return st; |
431 | } |
432 | |
433 | TopAbs_Orientation o1 = Ori(iSTA,1), o2 = Ori(iSTA,2); |
434 | TopAbs_State st1 = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o1) : |
435 | TopTrans_SurfaceTransition::GetAfter(o1); |
436 | TopAbs_State st2 = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o2) : |
437 | TopTrans_SurfaceTransition::GetAfter(o2); |
438 | if (st1 != st2) return TopAbs_UNKNOWN; // Incoherent data |
439 | return st1; |
440 | } |
441 | |
442 | |
443 | TopAbs_State TopTrans_SurfaceTransition::StateBefore() const |
444 | { |
445 | if (!STATIC_DEFINED) return TopAbs_UNKNOWN; |
446 | |
447 | // we take the state before of before orientations |
448 | TopAbs_State before = ::FUN_getstate(myAng,myOri,BEFORE,BEFORE); |
449 | if (M_UNKNOWN(before)) { |
450 | // looking back in before for defined states |
451 | // we take the state before of after orientations |
452 | before = ::FUN_getstate(myAng,myOri,AFTER,BEFORE); |
453 | // eap Mar 25 2002 |
eafb234b |
454 | if (myTouchFlag) { |
7fd59977 |
455 | if (before == TopAbs_OUT) before = TopAbs_IN; |
456 | else if (before == TopAbs_IN) before = TopAbs_OUT; |
eafb234b |
457 | } |
7fd59977 |
458 | } |
459 | return before; |
460 | } |
461 | |
462 | TopAbs_State TopTrans_SurfaceTransition::StateAfter() const |
463 | { |
464 | if (!STATIC_DEFINED) return TopAbs_UNKNOWN; |
465 | |
466 | TopAbs_State after = ::FUN_getstate(myAng,myOri,AFTER,AFTER); |
467 | if (M_UNKNOWN(after)) { |
468 | // looking back in before for defined states |
469 | after = ::FUN_getstate(myAng,myOri,BEFORE,AFTER); |
470 | // eap Mar 25 2002 |
eafb234b |
471 | if (myTouchFlag) { |
7fd59977 |
472 | if (after == TopAbs_OUT) after = TopAbs_IN; |
473 | else if (after == TopAbs_IN) after = TopAbs_OUT; |
eafb234b |
474 | } |
7fd59977 |
475 | } |
476 | return after; |
477 | } |
478 | |
479 | TopAbs_State TopTrans_SurfaceTransition::GetBefore |
480 | (const TopAbs_Orientation Tran) |
481 | { |
482 | if (!STATIC_DEFINED) return TopAbs_UNKNOWN; |
483 | |
484 | switch (Tran) |
485 | { |
486 | case TopAbs_FORWARD : |
487 | case TopAbs_EXTERNAL : |
488 | return TopAbs_OUT; |
489 | case TopAbs_REVERSED : |
490 | case TopAbs_INTERNAL : |
491 | return TopAbs_IN; |
492 | } |
493 | return TopAbs_OUT; |
494 | } |
495 | |
496 | TopAbs_State TopTrans_SurfaceTransition::GetAfter |
497 | (const TopAbs_Orientation Tran) |
498 | { |
499 | if (!STATIC_DEFINED) return TopAbs_UNKNOWN; |
500 | |
501 | switch (Tran) |
502 | { |
503 | case TopAbs_FORWARD : |
504 | case TopAbs_INTERNAL : |
505 | return TopAbs_IN; |
506 | case TopAbs_REVERSED : |
507 | case TopAbs_EXTERNAL : |
508 | return TopAbs_OUT; |
509 | } |
510 | return TopAbs_OUT; |
511 | } |