// Created on: 1997-03-04 // Created by: Prestataire Xuan PHAM PHU // Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // Modified: eap Mar 25 2002 (occ102,occ227), touch case #include #include #include #include #include #include static Standard_Boolean STATIC_DEFINED = Standard_False; static gp_Dir FUN_nCinsideS(const gp_Dir& tgC, const gp_Dir& ngS) { // Give us a curve C on suface S, , a parameter // Purpose : compute normal vector to C, tangent to S at // given point , oriented INSIDE S // : geometric tangent at point of // : geometric normal at point of gp_Dir XX(ngS^tgC); return XX; } #define M_REVERSED(st) (st == TopAbs_REVERSED) #define M_INTERNAL(st) (st == TopAbs_INTERNAL) #define M_UNKNOWN(st) (st == TopAbs_UNKNOWN) static Standard_Integer FUN_OO(const Standard_Integer i) { if (i == 1) return 2; if (i == 2) return 1; return 0; } //static Standard_Real FUN_Ang(const gp_Dir& Normref, static Standard_Real FUN_Ang(const gp_Dir& , const gp_Dir& beafter, const gp_Dir& TgC, const gp_Dir& Norm, const TopAbs_Orientation O) { gp_Dir dironF = FUN_nCinsideS(TgC,Norm); if (M_REVERSED(O)) dironF.Reverse(); Standard_Real ang = beafter.AngleWithRef(dironF,TgC); return ang; } static void FUN_getSTA(const Standard_Real Ang, const Standard_Real tola, Standard_Integer& i, Standard_Integer& j) { Standard_Real cos = Cos(Ang); Standard_Real sin = Sin(Ang); Standard_Boolean nullcos = Abs(cos) < tola; Standard_Boolean nullsin = Abs(sin) < tola; if (nullcos) i = 0; else i = (cos > 0.) ? 1 : 2; if (nullsin) j = 0; else j = (sin > 0.) ? 1 : 2; } /*static void FUN_getSTA(const Standard_Real Ang, const Standard_Real tola, const Standard_Real Curv, const Standard_Real CurvRef, Standard_Integer& i, Standard_Integer& j) { // Choosing UV referential (beafter,myNorm). // purpose : computes position boundary face relative to the reference surface // notice : j==0 => j==1 : the boundary face is ABOVE the reference surface // j==2 : the boundary face is UNDER the reference surface // - j==0 : the boundary and the reference objects are tangent- FUN_getSTA(Ang,tola,i,j); if (j == 0) { Standard_Real diff = Curv - CurvRef; if (Abs(diff) < tola) {STATIC_DEFINED = Standard_False; return;} // nyi FUN_Raise j = (diff < 0.) ? 1 : 2; } }*/ #ifndef OCCT_DEBUG #define M_Unknown (-100) #else #define M_Unknown (-100.) #endif #define M_noupdate (0) #define M_updateREF (1) #define M_Ointernal (10) static Standard_Integer FUN_refnearest(const Standard_Real Angref, const TopAbs_Orientation Oriref, const Standard_Real Ang, const TopAbs_Orientation Ori, const Standard_Real tola) { Standard_Boolean undef = (Angref == 100.); if (undef) return M_updateREF; Standard_Real cosref = Cos(Angref), cos = Cos(Ang); Standard_Real dcos = Abs(cosref) - Abs(cos); if (Abs(dcos) < tola) { // Analysis for tangent cases : if two boundary faces are same sided // and have tangent normals, if they have opposite orientations // we choose INTERNAL as resulting complex transition (case EXTERNAL // refering to no logical case) if (TopAbs::Complement(Ori) == Oriref) return M_Ointernal; else return (Standard_Integer ) M_Unknown; // nyi FUN_RAISE } Standard_Integer updateref = (dcos > 0.)? M_noupdate : M_updateREF; return updateref; } //======================================================================= //function : FUN_refnearest //purpose : //======================================================================= static Standard_Integer 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) // eap Mar 25 2002 { Standard_Boolean iisj = (i == j); Standard_Real abscos = Abs(Cos(Ang)); Standard_Boolean i0 = (Abs(1. - abscos) < tola); Standard_Boolean j0 = (abscos < tola); Standard_Boolean nullcurv = (Curv == 0.); Standard_Boolean curvpos = (Curv > tola); Standard_Boolean curvneg = (Curv < -tola); Standard_Boolean nullcsref = (CurvSref == 0.); Standard_Boolean undef = (Angref == 100.); if (undef) { if (i0) { if (iisj && curvneg) return M_noupdate; if (!iisj && curvpos) return M_noupdate; } if (j0) { if (!nullcsref && (j == 1) && iisj && (curvpos || nullcurv)) return M_updateREF; if (!nullcsref && (j == 1) && !iisj && (curvneg || nullcurv)) return M_updateREF; if (iisj && curvpos) return M_noupdate; if (!iisj && curvneg) return M_noupdate; } return M_updateREF; } // undef Standard_Real cosref = Cos(Angref), cos = Cos(Ang); Standard_Real dcos = Abs(cosref) - Abs(cos); Standard_Boolean samecos = Abs(dcos) < tola; if (samecos) { // Analysis for tangent cases : if two boundary faces are same sided // and have sma dironF. if (Abs(Curvref - Curv) < 1.e-4) { if (TopAbs::Complement(Ori) == Oriref) return M_Ointernal; else return (Standard_Integer ) M_Unknown; // nyi FUN_RAISE } Standard_Boolean noupdate = Standard_False; if (iisj && (Curvref > Curv)) noupdate = Standard_True; if (!iisj && (Curvref < Curv)) noupdate = Standard_True; Standard_Integer updateref = noupdate ? M_noupdate : M_updateREF; if (!j0) return updateref; if (!noupdate && !nullcsref) { // check for (j==1) the face is ABOVE Sref // check for (j==2) the face is BELOW Sref if ((j == 2) && (Abs(Curv) < CurvSref)) updateref = M_noupdate; if ((j == 1) && (Abs(Curv) > CurvSref)) updateref = M_noupdate; } return updateref; } // samecos Standard_Integer updateref = (dcos > 0.)? M_noupdate : M_updateREF; if (Oriref != Ori) TouchFlag = Standard_True; // eap Mar 25 2002 return updateref; } // ============================================================ // methods // ============================================================ TopTrans_SurfaceTransition::TopTrans_SurfaceTransition() : myAng(1,2,1,2),myCurv(1,2,1,2),myOri(1,2,1,2) { STATIC_DEFINED = Standard_False; } void TopTrans_SurfaceTransition::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) { STATIC_DEFINED = Standard_True; Standard_Real tola = Precision::Angular(); Standard_Boolean curismax = (Abs(MaxD.Dot(myTgt)) < tola); Standard_Boolean curismin = (Abs(MinD.Dot(myTgt)) < tola); if ((Abs(MaxCurv) < tola) && (Abs(MinCurv) < tola)) { Reset(Tgt,Norm); return; } if (!curismax && !curismin) { // In the plane normal to , we see the boundary face as // a boundary curve. // NYIxpu : compute the curvature of the curve if not MaxCurv // nor MinCurv. STATIC_DEFINED = Standard_False; return; } if (curismax) myCurvRef = Abs(MaxCurv); if (curismin) myCurvRef = Abs(MinCurv); if (myCurvRef < tola) myCurvRef = 0.; // ============================================================ // recall : is oriented OUTSIDE the "geometric matter" described // by the surface // - if (myCurvRef != 0.) Sref is UNDER axis (sin = 0) // referential (beafter,myNorm,myTgt) - // ============================================================ // beafter oriented (before, after) the intersection on the reference surface. myNorm = Norm; myTgt = Tgt; beafter = Norm^Tgt; for (Standard_Integer i = 1; i <=2; i++) for (Standard_Integer j = 1; j <=2; j++) myAng(i,j) = 100.; myTouchFlag = Standard_False; // eap Mar 25 2002 } void TopTrans_SurfaceTransition::Reset(const gp_Dir& Tgt, const gp_Dir& Norm) { STATIC_DEFINED = Standard_True; // beafter oriented (before, after) the intersection on the reference surface. myNorm = Norm; myTgt = Tgt; beafter = Norm^Tgt; for (Standard_Integer i = 1; i <=2; i++) for (Standard_Integer j = 1; j <=2; j++) myAng(i,j) = 100.; myCurvRef = 0.; myTouchFlag = Standard_False; // eap Mar 25 2002 } void TopTrans_SurfaceTransition::Compare //(const Standard_Real Tole, (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) { if (!STATIC_DEFINED) return; Standard_Real Curv=0.; // ------ Standard_Real tola = Precision::Angular(); Standard_Boolean curismax = (Abs(MaxD.Dot(myTgt)) < tola); Standard_Boolean curismin = (Abs(MinD.Dot(myTgt)) < tola); if (!curismax && !curismin) { // In the plane normal to , we see the boundary face as // a boundary curve. // NYIxpu : compute the curvature of the curve if not MaxCurv // nor MinCurv. STATIC_DEFINED = Standard_False; return; } if (curismax) Curv = Abs(MaxCurv); if (curismin) Curv = Abs(MinCurv); if (myCurvRef < tola) Curv = 0.; gp_Dir dironF = FUN_nCinsideS(myTgt,Norm); Standard_Real prod = (dironF^Norm).Dot(myTgt); if (prod < 0.) Curv = -Curv; Standard_Real Ang; // ----- Ang = ::FUN_Ang(myNorm,beafter,myTgt,Norm,O); Standard_Integer i,j; // ----- // i = 0,1,2 : cos = 0,>0,<0 // j = 0,1,2 : sin = 0,>0,<0 ::FUN_getSTA(Ang,tola,i,j); // update nearest : // --------------- Standard_Integer kmax = M_INTERNAL(O) ? 2 : 1; for (Standard_Integer k=1; k <=kmax; k++) { if (k == 2) { // get the opposite Ang i = ::FUN_OO(i); j = ::FUN_OO(j); } Standard_Boolean i0 = (i == 0), j0 = (j == 0); Standard_Integer nmax = (i0 || j0) ? 2 : 1; for (Standard_Integer n=1; n<=nmax; n++) { if (i0) i = n; if (j0) j = n; // if (curvref == 0.) : // Standard_Boolean iisj = (i == j); // Standard_Boolean Curvpos = (Curv > 0.); // if ((Curv != 0.) && i0) { // if (iisj && !Curvpos) continue; // if (!iisj && Curvpos) continue; // } // if ((Curv != 0.) && j0) { // if (iisj && Curvpos) continue; // if (!iisj && !Curvpos) continue; // } Standard_Integer refn = ::FUN_refnearest(i,j,myCurvRef,myAng(i,j),myOri(i,j),myCurv(i,j), Ang,/*O*/S,Curv,tola,myTouchFlag); // eap Mar 25 2002 if (refn == M_Unknown) {STATIC_DEFINED = Standard_False; return;} if (refn > 0) { myAng(i,j) = Ang; myOri(i,j) = (refn == M_Ointernal) ? TopAbs_INTERNAL : S; myCurv(i,j) = Curv; } } // n=1..nmax } // k=1..kmax } void TopTrans_SurfaceTransition::Compare //(const Standard_Real Tole, (const Standard_Real , const gp_Dir& Norm, const TopAbs_Orientation S, const TopAbs_Orientation O) { if (!STATIC_DEFINED) return; // oriented Ang(beafter,dironF), // dironF normal to the curve, oriented INSIDE F, the added oriented support Standard_Real Ang = ::FUN_Ang(myNorm,beafter,myTgt,Norm,O); Standard_Real tola = Precision::Angular(); // nyi in arg // i = 0,1,2 : cos = 0,>0,<0 // j = 0,1,2 : sin = 0,>0,<0 Standard_Integer i,j; ::FUN_getSTA(Ang,tola,i,j); Standard_Integer kmax = M_INTERNAL(O) ? 2 : 1; for (Standard_Integer k=1; k <=kmax; k++) { if (k == 2) { // get the opposite Ang i = ::FUN_OO(i); j = ::FUN_OO(j); } Standard_Boolean i0 = (i == 0), j0 = (j == 0); Standard_Integer nmax = (i0 || j0) ? 2 : 1; for (Standard_Integer n=1; n<=nmax; n++) { if (i0) i = n; if (j0) j = n; Standard_Integer refn = ::FUN_refnearest(myAng(i,j),myOri(i,j), Ang,/*O*/S,tola); // eap if (refn == M_Unknown) {STATIC_DEFINED = Standard_False; return;} if (refn > 0) { myAng(i,j) = Ang; myOri(i,j) = (refn == M_Ointernal) ? TopAbs_INTERNAL : S; } } // n=1..nmax } // k=1..kmax } #define BEFORE (2) #define AFTER (1) static TopAbs_State FUN_getstate(const TColStd_Array2OfReal& Ang, const TopTrans_Array2OfOrientation& Ori, const Standard_Integer iSTA, const Standard_Integer iINDEX) { if (!STATIC_DEFINED) return TopAbs_UNKNOWN; Standard_Real a1 = Ang(iSTA,1), a2 = Ang(iSTA,2); Standard_Boolean undef1 = (a1 == 100.), undef2 = (a2 == 100.); Standard_Boolean undef = undef1 && undef2; if (undef) return TopAbs_UNKNOWN; if (undef1 || undef2) { Standard_Integer jok = undef1 ? 2 : 1; TopAbs_Orientation o = Ori(iSTA,jok); TopAbs_State st = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o) : TopTrans_SurfaceTransition::GetAfter(o); return st; } TopAbs_Orientation o1 = Ori(iSTA,1), o2 = Ori(iSTA,2); TopAbs_State st1 = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o1) : TopTrans_SurfaceTransition::GetAfter(o1); TopAbs_State st2 = (iINDEX == BEFORE) ? TopTrans_SurfaceTransition::GetBefore(o2) : TopTrans_SurfaceTransition::GetAfter(o2); if (st1 != st2) return TopAbs_UNKNOWN; // Incoherent data return st1; } TopAbs_State TopTrans_SurfaceTransition::StateBefore() const { if (!STATIC_DEFINED) return TopAbs_UNKNOWN; // we take the state before of before orientations TopAbs_State before = ::FUN_getstate(myAng,myOri,BEFORE,BEFORE); if (M_UNKNOWN(before)) { // looking back in before for defined states // we take the state before of after orientations before = ::FUN_getstate(myAng,myOri,AFTER,BEFORE); // eap Mar 25 2002 if (myTouchFlag) { if (before == TopAbs_OUT) before = TopAbs_IN; else if (before == TopAbs_IN) before = TopAbs_OUT; } } return before; } TopAbs_State TopTrans_SurfaceTransition::StateAfter() const { if (!STATIC_DEFINED) return TopAbs_UNKNOWN; TopAbs_State after = ::FUN_getstate(myAng,myOri,AFTER,AFTER); if (M_UNKNOWN(after)) { // looking back in before for defined states after = ::FUN_getstate(myAng,myOri,BEFORE,AFTER); // eap Mar 25 2002 if (myTouchFlag) { if (after == TopAbs_OUT) after = TopAbs_IN; else if (after == TopAbs_IN) after = TopAbs_OUT; } } return after; } TopAbs_State TopTrans_SurfaceTransition::GetBefore (const TopAbs_Orientation Tran) { if (!STATIC_DEFINED) return TopAbs_UNKNOWN; switch (Tran) { case TopAbs_FORWARD : case TopAbs_EXTERNAL : return TopAbs_OUT; case TopAbs_REVERSED : case TopAbs_INTERNAL : return TopAbs_IN; } return TopAbs_OUT; } TopAbs_State TopTrans_SurfaceTransition::GetAfter (const TopAbs_Orientation Tran) { if (!STATIC_DEFINED) return TopAbs_UNKNOWN; switch (Tran) { case TopAbs_FORWARD : case TopAbs_INTERNAL : return TopAbs_IN; case TopAbs_REVERSED : case TopAbs_EXTERNAL : return TopAbs_OUT; } return TopAbs_OUT; }