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