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