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