0025418: Debug output to be limited to OCC development environment
[occt.git] / src / TopTrans / TopTrans_SurfaceTransition.cxx
CommitLineData
b311480e 1// Created on: 1997-03-04
2// Created by: Prestataire Xuan PHAM PHU
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 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
34static Standard_Boolean STATIC_DEFINED = Standard_False;
35
36//#include <TopOpeBRepTool_EXPORT.hxx>
37static 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
52static 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,
60static 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
73static 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}*/
0797d9d3 103#ifndef OCCT_DEBUG
7fd59977 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)
111static 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
136static 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
209TopTrans_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
215void 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
263void 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
280void 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
362void 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)
408static 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
438TopAbs_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
eafb234b 449 if (myTouchFlag) {
7fd59977 450 if (before == TopAbs_OUT) before = TopAbs_IN;
451 else if (before == TopAbs_IN) before = TopAbs_OUT;
eafb234b 452 }
7fd59977 453 }
454 return before;
455}
456
457TopAbs_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
eafb234b 466 if (myTouchFlag) {
7fd59977 467 if (after == TopAbs_OUT) after = TopAbs_IN;
468 else if (after == TopAbs_IN) after = TopAbs_OUT;
eafb234b 469 }
7fd59977 470 }
471 return after;
472}
473
474TopAbs_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
491TopAbs_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}