0023024: Update headers of OCCT files
[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-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
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 
454     if (myTouchFlag)
455       if (before == TopAbs_OUT) before = TopAbs_IN;
456       else if (before == TopAbs_IN) before = TopAbs_OUT;
457   }
458   return before;
459 }
460
461 TopAbs_State TopTrans_SurfaceTransition::StateAfter() const
462 {
463   if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
464
465   TopAbs_State after = ::FUN_getstate(myAng,myOri,AFTER,AFTER);
466   if (M_UNKNOWN(after)) {
467     // looking back in before for defined states
468     after = ::FUN_getstate(myAng,myOri,BEFORE,AFTER);
469     // eap Mar 25 2002 
470     if (myTouchFlag)
471       if (after == TopAbs_OUT) after = TopAbs_IN;
472       else if (after == TopAbs_IN) after = TopAbs_OUT;
473   }
474   return after;
475 }
476
477 TopAbs_State TopTrans_SurfaceTransition::GetBefore
478 (const TopAbs_Orientation Tran)
479 {
480   if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
481
482   switch (Tran)
483     {
484     case TopAbs_FORWARD  :
485     case TopAbs_EXTERNAL :
486       return TopAbs_OUT;
487     case TopAbs_REVERSED :
488     case TopAbs_INTERNAL :
489       return TopAbs_IN;
490     }
491   return TopAbs_OUT;
492 }
493
494 TopAbs_State TopTrans_SurfaceTransition::GetAfter
495 (const TopAbs_Orientation Tran)
496 {
497   if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
498
499   switch (Tran)
500     {
501     case TopAbs_FORWARD  :
502     case TopAbs_INTERNAL :
503       return TopAbs_IN;
504     case TopAbs_REVERSED :
505     case TopAbs_EXTERNAL :
506       return TopAbs_OUT;
507     }
508   return TopAbs_OUT;
509 }