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
FUN_nCinsideS(const gp_Dir & tgC,const gp_Dir & ngS)28 static gp_Dir FUN_nCinsideS(const gp_Dir& tgC, const gp_Dir& ngS)
29 {
30 // Give us a curve C on surface 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
FUN_OO(const Standard_Integer i)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,
FUN_Ang(const gp_Dir &,const gp_Dir & beafter,const gp_Dir & TgC,const gp_Dir & Norm,const TopAbs_Orientation O)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
FUN_getSTA(const Standard_Real Ang,const Standard_Real tola,Standard_Integer & i,Standard_Integer & j)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)
FUN_refnearest(const Standard_Real Angref,const TopAbs_Orientation Oriref,const Standard_Real Ang,const TopAbs_Orientation Ori,const Standard_Real tola)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 // referring 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
FUN_refnearest(const Standard_Integer i,const Standard_Integer j,const Standard_Real CurvSref,const Standard_Real Angref,const TopAbs_Orientation Oriref,const Standard_Real Curvref,const Standard_Real Ang,const TopAbs_Orientation Ori,const Standard_Real Curv,const Standard_Real tola,Standard_Boolean & TouchFlag)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
TopTrans_SurfaceTransition()200 TopTrans_SurfaceTransition::TopTrans_SurfaceTransition()
201 : myCurvRef(0.0),
202 myAng(1, 2, 1, 2),
203 myCurv(1, 2, 1, 2),
204 myOri(1, 2, 1, 2),
205 myTouchFlag(Standard_False)
206 {
207 STATIC_DEFINED = Standard_False;
208 }
209
Reset(const gp_Dir & Tgt,const gp_Dir & Norm,const gp_Dir & MaxD,const gp_Dir & MinD,const Standard_Real MaxCurv,const Standard_Real MinCurv)210 void TopTrans_SurfaceTransition::Reset(const gp_Dir& Tgt,
211 const gp_Dir& Norm,
212 const gp_Dir& MaxD,const gp_Dir& MinD,
213 const Standard_Real MaxCurv,const Standard_Real MinCurv)
214 {
215 STATIC_DEFINED = Standard_True;
216
217 Standard_Real tola = Precision::Angular();
218 Standard_Boolean curismax = (Abs(MaxD.Dot(myTgt)) < tola);
219 Standard_Boolean curismin = (Abs(MinD.Dot(myTgt)) < tola);
220
221 if ((Abs(MaxCurv) < tola) && (Abs(MinCurv) < tola)) {
222 Reset(Tgt,Norm);
223 return;
224 }
225
226 if (!curismax && !curismin) {
227 // In the plane normal to <myTgt>, we see the boundary face as
228 // a boundary curve.
229 // NYIxpu : compute the curvature of the curve if not MaxCurv
230 // nor MinCurv.
231
232 STATIC_DEFINED = Standard_False;
233 return;
234 }
235
236 if (curismax) myCurvRef = Abs(MaxCurv);
237 if (curismin) myCurvRef = Abs(MinCurv);
238 if (myCurvRef < tola) myCurvRef = 0.;
239
240 // ============================================================
241 // recall : <Norm> is oriented OUTSIDE the "geometric matter" described
242 // by the surface
243 // - if (myCurvRef != 0.) Sref is UNDER axis (sin = 0)
244 // referential (beafter,myNorm,myTgt) -
245 // ============================================================
246
247 // beafter oriented (before, after) the intersection on the reference surface.
248 myNorm = Norm;
249 myTgt = Tgt;
250 beafter = Norm^Tgt;
251 for (Standard_Integer i = 1; i <=2; i++)
252 for (Standard_Integer j = 1; j <=2; j++)
253 myAng(i,j) = 100.;
254
255 myTouchFlag = Standard_False; // eap Mar 25 2002
256 }
257
Reset(const gp_Dir & Tgt,const gp_Dir & Norm)258 void TopTrans_SurfaceTransition::Reset(const gp_Dir& Tgt,
259 const gp_Dir& Norm)
260 {
261 STATIC_DEFINED = Standard_True;
262
263 // beafter oriented (before, after) the intersection on the reference surface.
264 myNorm = Norm;
265 myTgt = Tgt;
266 beafter = Norm^Tgt;
267 for (Standard_Integer i = 1; i <=2; i++)
268 for (Standard_Integer j = 1; j <=2; j++)
269 myAng(i,j) = 100.;
270
271 myCurvRef = 0.;
272 myTouchFlag = Standard_False; // eap Mar 25 2002
273 }
274
Compare(const Standard_Real,const gp_Dir & Norm,const gp_Dir & MaxD,const gp_Dir & MinD,const Standard_Real MaxCurv,const Standard_Real MinCurv,const TopAbs_Orientation S,const TopAbs_Orientation O)275 void TopTrans_SurfaceTransition::Compare
276 //(const Standard_Real Tole,
277 (const Standard_Real ,
278 const gp_Dir& Norm,
279 const gp_Dir& MaxD,const gp_Dir& MinD,
280 const Standard_Real MaxCurv,const Standard_Real MinCurv,
281 const TopAbs_Orientation S,
282 const TopAbs_Orientation O)
283 {
284 if (!STATIC_DEFINED) return;
285
286 Standard_Real Curv=0.;
287 // ------
288 Standard_Real tola = Precision::Angular();
289 Standard_Boolean curismax = (Abs(MaxD.Dot(myTgt)) < tola);
290 Standard_Boolean curismin = (Abs(MinD.Dot(myTgt)) < tola);
291 if (!curismax && !curismin) {
292 // In the plane normal to <myTgt>, we see the boundary face as
293 // a boundary curve.
294 // NYIxpu : compute the curvature of the curve if not MaxCurv
295 // nor MinCurv.
296
297 STATIC_DEFINED = Standard_False;
298 return;
299 }
300 if (curismax) Curv = Abs(MaxCurv);
301 if (curismin) Curv = Abs(MinCurv);
302 if (myCurvRef < tola) Curv = 0.;
303 gp_Dir dironF = FUN_nCinsideS(myTgt,Norm);
304 Standard_Real prod = (dironF^Norm).Dot(myTgt);
305 if (prod < 0.) Curv = -Curv;
306
307 Standard_Real Ang;
308 // -----
309 Ang = ::FUN_Ang(myNorm,beafter,myTgt,Norm,O);
310
311 Standard_Integer i,j;
312 // -----
313 // i = 0,1,2 : cos = 0,>0,<0
314 // j = 0,1,2 : sin = 0,>0,<0
315 ::FUN_getSTA(Ang,tola,i,j);
316
317 // update nearest :
318 // ---------------
319 Standard_Integer kmax = M_INTERNAL(O) ? 2 : 1;
320 for (Standard_Integer k=1; k <=kmax; k++) {
321 if (k == 2) {
322 // get the opposite Ang
323 i = ::FUN_OO(i);
324 j = ::FUN_OO(j);
325 }
326 Standard_Boolean i0 = (i == 0), j0 = (j == 0);
327 Standard_Integer nmax = (i0 || j0) ? 2 : 1;
328 for (Standard_Integer n=1; n<=nmax; n++) {
329 if (i0) i = n;
330 if (j0) j = n;
331
332 // if (curvref == 0.) :
333 // Standard_Boolean iisj = (i == j);
334 // Standard_Boolean Curvpos = (Curv > 0.);
335 // if ((Curv != 0.) && i0) {
336 // if (iisj && !Curvpos) continue;
337 // if (!iisj && Curvpos) continue;
338 // }
339 // if ((Curv != 0.) && j0) {
340 // if (iisj && Curvpos) continue;
341 // if (!iisj && !Curvpos) continue;
342 // }
343
344 Standard_Integer refn = ::FUN_refnearest(i,j,myCurvRef,myAng(i,j),myOri(i,j),myCurv(i,j),
345 Ang,/*O*/S,Curv,tola,myTouchFlag); // eap Mar 25 2002
346 if (refn == M_Unknown) {STATIC_DEFINED = Standard_False; return;}
347 if (refn > 0) {
348 myAng(i,j) = Ang;
349 myOri(i,j) = (refn == M_Ointernal) ? TopAbs_INTERNAL : S;
350 myCurv(i,j) = Curv;
351 }
352 } // n=1..nmax
353 } // k=1..kmax
354
355 }
356
Compare(const Standard_Real,const gp_Dir & Norm,const TopAbs_Orientation S,const TopAbs_Orientation O)357 void TopTrans_SurfaceTransition::Compare
358 //(const Standard_Real Tole,
359 (const Standard_Real ,
360 const gp_Dir& Norm,
361 const TopAbs_Orientation S,
362 const TopAbs_Orientation O)
363 {
364 if (!STATIC_DEFINED) return;
365
366 // oriented Ang(beafter,dironF),
367 // dironF normal to the curve, oriented INSIDE F, the added oriented support
368 Standard_Real Ang = ::FUN_Ang(myNorm,beafter,myTgt,Norm,O);
369 Standard_Real tola = Precision::Angular(); // nyi in arg
370
371 // i = 0,1,2 : cos = 0,>0,<0
372 // j = 0,1,2 : sin = 0,>0,<0
373 Standard_Integer i,j; ::FUN_getSTA(Ang,tola,i,j);
374
375 Standard_Integer kmax = M_INTERNAL(O) ? 2 : 1;
376 for (Standard_Integer k=1; k <=kmax; k++) {
377 if (k == 2) {
378 // get the opposite Ang
379 i = ::FUN_OO(i);
380 j = ::FUN_OO(j);
381 }
382
383 Standard_Boolean i0 = (i == 0), j0 = (j == 0);
384 Standard_Integer nmax = (i0 || j0) ? 2 : 1;
385 for (Standard_Integer n=1; n<=nmax; n++) {
386 if (i0) i = n;
387 if (j0) j = n;
388
389 Standard_Integer refn = ::FUN_refnearest(myAng(i,j),myOri(i,j),
390 Ang,/*O*/S,tola); // eap
391 if (refn == M_Unknown) {STATIC_DEFINED = Standard_False; return;}
392
393 if (refn > 0) {
394 myAng(i,j) = Ang;
395 myOri(i,j) = (refn == M_Ointernal) ? TopAbs_INTERNAL : S;
396 }
397 } // n=1..nmax
398 } // k=1..kmax
399 }
400
401 #define BEFORE (2)
402 #define AFTER (1)
FUN_getstate(const TColStd_Array2OfReal & Ang,const TopTrans_Array2OfOrientation & Ori,const Standard_Integer iSTA,const Standard_Integer iINDEX)403 static TopAbs_State FUN_getstate(const TColStd_Array2OfReal& Ang,
404 const TopTrans_Array2OfOrientation& Ori,
405 const Standard_Integer iSTA,
406 const Standard_Integer iINDEX)
407 {
408 if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
409
410 Standard_Real a1 = Ang(iSTA,1), a2 = Ang(iSTA,2);
411 Standard_Boolean undef1 = (a1 == 100.), undef2 = (a2 == 100.);
412 Standard_Boolean undef = undef1 && undef2;
413 if (undef) return TopAbs_UNKNOWN;
414
415 if (undef1 || undef2) {
416 Standard_Integer jok = undef1 ? 2 : 1;
417 TopAbs_Orientation o = Ori(iSTA,jok);
418 TopAbs_State st = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o) :
419 TopTrans_SurfaceTransition::GetAfter(o);
420 return st;
421 }
422
423 TopAbs_Orientation o1 = Ori(iSTA,1), o2 = Ori(iSTA,2);
424 TopAbs_State st1 = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o1) :
425 TopTrans_SurfaceTransition::GetAfter(o1);
426 TopAbs_State st2 = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o2) :
427 TopTrans_SurfaceTransition::GetAfter(o2);
428 if (st1 != st2) return TopAbs_UNKNOWN; // Incoherent data
429 return st1;
430 }
431
432
StateBefore() const433 TopAbs_State TopTrans_SurfaceTransition::StateBefore() const
434 {
435 if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
436
437 // we take the state before of before orientations
438 TopAbs_State before = ::FUN_getstate(myAng,myOri,BEFORE,BEFORE);
439 if (M_UNKNOWN(before)) {
440 // looking back in before for defined states
441 // we take the state before of after orientations
442 before = ::FUN_getstate(myAng,myOri,AFTER,BEFORE);
443 // eap Mar 25 2002
444 if (myTouchFlag) {
445 if (before == TopAbs_OUT) before = TopAbs_IN;
446 else if (before == TopAbs_IN) before = TopAbs_OUT;
447 }
448 }
449 return before;
450 }
451
StateAfter() const452 TopAbs_State TopTrans_SurfaceTransition::StateAfter() const
453 {
454 if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
455
456 TopAbs_State after = ::FUN_getstate(myAng,myOri,AFTER,AFTER);
457 if (M_UNKNOWN(after)) {
458 // looking back in before for defined states
459 after = ::FUN_getstate(myAng,myOri,BEFORE,AFTER);
460 // eap Mar 25 2002
461 if (myTouchFlag) {
462 if (after == TopAbs_OUT) after = TopAbs_IN;
463 else if (after == TopAbs_IN) after = TopAbs_OUT;
464 }
465 }
466 return after;
467 }
468
GetBefore(const TopAbs_Orientation Tran)469 TopAbs_State TopTrans_SurfaceTransition::GetBefore
470 (const TopAbs_Orientation Tran)
471 {
472 if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
473
474 switch (Tran)
475 {
476 case TopAbs_FORWARD :
477 case TopAbs_EXTERNAL :
478 return TopAbs_OUT;
479 case TopAbs_REVERSED :
480 case TopAbs_INTERNAL :
481 return TopAbs_IN;
482 }
483 return TopAbs_OUT;
484 }
485
GetAfter(const TopAbs_Orientation Tran)486 TopAbs_State TopTrans_SurfaceTransition::GetAfter
487 (const TopAbs_Orientation Tran)
488 {
489 if (!STATIC_DEFINED) return TopAbs_UNKNOWN;
490
491 switch (Tran)
492 {
493 case TopAbs_FORWARD :
494 case TopAbs_INTERNAL :
495 return TopAbs_IN;
496 case TopAbs_REVERSED :
497 case TopAbs_EXTERNAL :
498 return TopAbs_OUT;
499 }
500 return TopAbs_OUT;
501 }
502