0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / TopOpeBRepDS / TopOpeBRepDS_FaceInterferenceTool.cxx
1 // Created on: 1994-11-08
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1994-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 #include <TopOpeBRepDS_FaceInterferenceTool.ixx>
18
19 #include <Extrema_ExtPS.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve2d.hxx>
22 #include <BRepAdaptor_Surface.hxx>
23 #include <BRepLProp_SLProps.hxx>
24 #include <TopoDS.hxx>
25 #include <TopExp_Explorer.hxx>
26 #include <Precision.hxx>
27 #include <gp_Sphere.hxx>
28 #include <Standard_ProgramError.hxx>
29 #include <TopOpeBRepDS_ProcessInterferencesTool.hxx>
30 #include <TopOpeBRepTool_ShapeTool.hxx>
31 #include <TopOpeBRepTool_EXPORT.hxx>
32 #include <TopOpeBRepTool_TOOL.hxx>
33 #include <TopOpeBRepDS_define.hxx>
34 #include <TopOpeBRepDS_ShapeShapeInterference.hxx>
35
36 #ifdef OCCT_DEBUG
37 extern Standard_Boolean TopOpeBRepDS_GettraceSTRANGE();
38 extern Standard_Boolean TopOpeBRepDS_GettracePEI();
39 extern Standard_Boolean TopOpeBRepDS_GettracePFI();
40 extern Standard_Boolean TopOpeBRepDS_GettracePI();
41 extern Standard_Boolean TopOpeBRepDS_GettraceSPSX(const Standard_Integer);
42 static Standard_Boolean FTRCF(const Standard_Integer F) {
43   Standard_Boolean b1 = TopOpeBRepDS_GettracePFI();
44   Standard_Boolean b2 = TopOpeBRepDS_GettracePI();
45   Standard_Boolean b3 = TopOpeBRepDS_GettraceSPSX(F);
46   return (b1 || b2 || b3);
47 }
48 //unreferenced function, commented 
49 /*
50 static Standard_Boolean FTRCE(const Standard_Integer E) {
51   Standard_Boolean b1 = TopOpeBRepDS_GettracePEI();
52   Standard_Boolean b2 = TopOpeBRepDS_GettracePI();
53   Standard_Boolean b3 = TopOpeBRepDS_GettraceSPSX(E);
54   return (b1 || b2 || b3);
55 }*/
56 extern void debredfac(const Standard_Integer I);
57 #endif
58
59 static Standard_Boolean STATIC_TOREVERSE = Standard_False; // xpu150498
60 #define M_FORWARD(ori) (ori == TopAbs_FORWARD)
61 #define M_REVERSED(ori) (ori == TopAbs_REVERSED)
62
63 //------------------------------------------------------
64 static void FUN_RaiseError(){Standard_ProgramError::Raise("TopOpeBRepDS_FaceInterferenceTool");}
65
66 //------------------------------------------------------
67 Standard_EXPORT Standard_Boolean FUN_Parameters
68 (const gp_Pnt& Pnt,const TopoDS_Shape& F,Standard_Real& u,Standard_Real& v)
69 {
70   BRepAdaptor_Surface Surf(TopoDS::Face(F));
71   // Get 2d coord of the projection of <Pnt> on surface of <F>.
72   Standard_Real uvtol = Surf.Tolerance();
73   Standard_Real fu=Surf.FirstUParameter(),lu=Surf.LastUParameter();
74   Standard_Real fv=Surf.FirstVParameter(),lv=Surf.LastVParameter();
75   Extrema_ExtPS extps(Pnt,Surf,fu,lu,fv,lv,uvtol,uvtol);
76   if (!extps.IsDone()) {
77     return Standard_False;
78   }
79   if (extps.NbExt() == 0) {
80     return Standard_False;
81   }
82   extps.Point(1).Parameter(u,v);
83
84   // xpu281098 : CTS21216 (FIR, f4,e7on)
85   Standard_Real d2 = extps.SquareDistance(1);
86   Standard_Real tolF = BRep_Tool::Tolerance(TopoDS::Face(F));
87   Standard_Boolean ok = (d2 < tolF*tolF*1.e6); // NYINYI
88   return ok;
89 }
90
91 //------------------------------------------------------
92 // Unused :
93 /*#ifdef OCCT_DEBUG
94 static Standard_Boolean FUN_Parameters
95 (const Standard_Real& Param,const TopoDS_Shape& E,const TopoDS_Shape& F,Standard_Real& u,Standard_Real& v)
96 {
97   // Get 2d coordinates of point of param <Param> on <E> of <F>.
98   BRepAdaptor_Curve2d curv2d(TopoDS::Edge(E),TopoDS::Face(F));
99   gp_Pnt2d p2d;
100   curv2d.D0(Param,p2d);
101   p2d.Coord(u,v);
102   return Standard_True;
103 }
104 #endif
105 */
106
107 //------------------------------------------------------
108 Standard_EXPORT void FUN_ComputeGeomData
109 (const TopoDS_Shape& F,const gp_Pnt2d& uv,gp_Dir& Norm)
110
111   gp_Vec ngF = FUN_tool_nggeomF(uv,TopoDS::Face(F));
112   Norm = gp_Dir(ngF);
113 }
114
115 //------------------------------------------------------
116 static Standard_Boolean FUN_sphere(const TopoDS_Shape& F)
117 {
118   Handle(Geom_Surface) su = TopOpeBRepTool_ShapeTool::BASISSURFACE(TopoDS::Face(F));
119   GeomAdaptor_Surface GAS(su);  
120   return (GAS.GetType() == GeomAbs_Sphere);
121 }
122
123 //------------------------------------------------------
124 //unreferenced function, commented 
125 /*#ifdef OCCT_DEBUG
126 static void FUN_middleUV(const TopoDS_Shape& F,Standard_Real& u,Standard_Real& v)
127 {
128   Handle(Geom_Surface) su = TopOpeBRepTool_ShapeTool::BASISSURFACE(TopoDS::Face(F));
129   GeomAdaptor_Surface GAS(su);
130   u = (GAS.LastUParameter() + GAS.FirstUParameter())*.5;
131   v = (GAS.LastVParameter() + GAS.FirstVParameter())*.5;
132 }
133 #endif*/
134
135 //------------------------------------------------------
136 Standard_EXPORT void FUN_ComputeGeomData
137 (const TopoDS_Shape& F,const gp_Pnt2d& uv,
138  gp_Dir& Norm,gp_Dir& D1,gp_Dir& D2,Standard_Real& Cur1,Standard_Real& Cur2)
139 {    
140   BRepAdaptor_Surface surf(TopoDS::Face(F));
141   Standard_Real uu = uv.X(),vv = uv.Y();
142   
143   Standard_Boolean sphere = FUN_sphere(F);
144   Standard_Boolean plane = FUN_tool_plane(F);
145   
146   // Getting the principle directions,the normal and the curvatures
147   BRepLProp_SLProps props(surf,uu,vv,2,Precision::Confusion());
148   Standard_Boolean curdef = props.IsCurvatureDefined();
149   if (!curdef) Standard_ProgramError::Raise("TopOpeBRepDS_FaceInterferenceTool::Init");
150   Standard_Boolean umbilic = props.IsUmbilic();
151   if (umbilic) { 
152     Cur1 = Cur2 = props.MeanCurvature(); 
153
154     // xpu030998 : cto901A3
155     Standard_Real toll = 1.e-8;
156     Standard_Boolean ooplane = (Abs(Cur1)<toll) && (Abs(Cur2)<toll);
157     plane = plane || ooplane;
158
159     if      (plane) 
160       Norm = FUN_tool_nggeomF(uv, TopoDS::Face(F));
161     else if (sphere) {
162       gp_Pnt center = surf.Sphere().Location();
163       gp_Pnt value  = surf.Value(uu,vv);  
164       Norm = gp_Dir(gp_Vec(center,value)); // recall : input data for TopTrans_SurfaceTransition
165                                            //          describes "direct" geometry 
166     }
167     else                
168       Standard_Failure::Raise("FUN_ComputeGeomData");
169     
170     D1 = Norm; Standard_Real x = D1.X(),y = D1.Y(),z = D1.Z(),tol = Precision::Confusion(); 
171     Standard_Boolean nullx = (Abs(x)<tol),nully = (Abs(y)<tol),nullz = (Abs(z)<tol);
172     if      (nullx && nully) D2 = gp_Dir(1,0,0);
173     else if (nullx && nullz) D2 = gp_Dir(1,0,0);
174     else if (nully && nullz) D2 = gp_Dir(0,1,0);
175     else                     D2 = gp_Dir(y*z,x*z,-2.*x*y);
176   }
177   else {
178     Cur1 = props.MaxCurvature();
179     Cur2 = props.MinCurvature();
180     props.CurvatureDirections(D1,D2);        
181     Norm = FUN_tool_nggeomF(uv,TopoDS::Face(F));
182   }
183 }
184
185 //=======================================================================
186 //function : TopOpeBRepDS_FaceInterferenceTool
187 //purpose  : 
188 //=======================================================================
189 TopOpeBRepDS_FaceInterferenceTool::TopOpeBRepDS_FaceInterferenceTool
190 (const TopOpeBRepDS_PDataStructure& PBDS)
191 : myPBDS(PBDS),myrefdef(Standard_False),myOnEdDef(Standard_False)
192 {
193 }
194
195 //=======================================================================
196 //function : Init
197 //purpose  : Initializes reference data for face/curve complex transition           
198 //=======================================================================
199 void TopOpeBRepDS_FaceInterferenceTool::Init
200 (const TopoDS_Shape& FFI,const TopoDS_Shape& EE,const Standard_Boolean EEisnew,const Handle(TopOpeBRepDS_Interference)& Iin)
201 {
202   Handle(TopOpeBRepDS_ShapeShapeInterference) I (Handle(TopOpeBRepDS_ShapeShapeInterference)::DownCast(Iin)); if (I.IsNull()) return;  
203   const TopoDS_Face& FI = TopoDS::Face(FFI);
204   const TopoDS_Edge& E = TopoDS::Edge(EE);
205 #ifdef OCCT_DEBUG
206 //  Standard_Integer iFI = myPBDS->Shape(FI);
207   //  Standard_Boolean TRCFI = FTRCF(iFI);if (TRCFI) debredfac(iFI);
208 #endif
209   
210   //   xpu150498
211   STATIC_TOREVERSE = Standard_False;
212   if (EEisnew) {
213     Standard_Integer G = I->Geometry(); const TopoDS_Edge& EG = TopoDS::Edge(myPBDS->Shape(G));    
214     TopOpeBRepDS_Config cf; Standard_Boolean cfok = FDS_Config3d(E,EG,cf);
215     if (!cfok) { FUN_RaiseError(); return; }
216     if (cf == TopOpeBRepDS_DIFFORIENTED) STATIC_TOREVERSE = Standard_True;
217   } // xpu150498
218
219   myFaceOrientation = FI.Orientation();
220   myFaceOriented    = I->Support();
221   
222   myEdge = E;
223   // Get a middle point on <E>
224   // Geometric data is described locally around this point.
225   // initialize : isLine,myParOnEd,myPntOnEd,myTole,Tgt.
226   
227   TopAbs_Orientation oEinFI; Standard_Boolean edonfa = FUN_tool_orientEinFFORWARD(E,FI,oEinFI);
228 //  isLine = FUN_tool_line(E);
229   isLine = Standard_False;
230   
231   if (!myOnEdDef) {
232     Standard_Boolean ok = FUN_tool_findPinE(E,myPntOnEd,myParOnEd);
233     if (!ok) { FUN_RaiseError(); return;}
234   }
235   
236   myTole = Precision::Angular();
237   gp_Pnt2d uv; Standard_Boolean ok = Standard_False; Standard_Real d = 0.;
238   if (edonfa) ok = FUN_tool_paronEF(E,myParOnEd,FI,uv);
239   else        ok = FUN_tool_projPonF(myPntOnEd,FI,uv,d);
240   if (!ok) { FUN_RaiseError(); return;}
241   
242   gp_Vec tmp; ok = TopOpeBRepTool_TOOL::TggeomE(myParOnEd,E,tmp);
243   if (!ok) { FUN_RaiseError(); return;}
244   gp_Dir Tgt(tmp);
245   gp_Dir Norm;
246   if(isLine) {
247     FUN_ComputeGeomData(FI,uv,Norm); 
248     myTool.Reset(Tgt,Norm);
249   }
250   else { 
251     gp_Dir D1,D2;
252     Standard_Real Cur1,Cur2;
253     FUN_ComputeGeomData(FI,uv,Norm,D1,D2,Cur1,Cur2);
254     myTool.Reset(Tgt,Norm,D1,D2,Cur1,Cur2); 
255   }
256   myrefdef = Standard_True;
257 }
258
259 //=======================================================================
260 //function : Add
261 //purpose  : 
262 //=======================================================================
263 void TopOpeBRepDS_FaceInterferenceTool::Add
264 (const TopoDS_Shape& FFI,const TopoDS_Shape& FFT,const TopoDS_Shape& EE,const Standard_Boolean EEisnew,const Handle(TopOpeBRepDS_Interference)& Iin)
265 {
266   Handle(TopOpeBRepDS_ShapeShapeInterference) I (Handle(TopOpeBRepDS_ShapeShapeInterference)::DownCast(Iin)); if (I.IsNull()) return;  
267   const TopoDS_Face& FI = TopoDS::Face(FFI);
268   const TopoDS_Face& FT = TopoDS::Face(FFT);
269   const TopoDS_Edge& E = TopoDS::Edge(EE);
270 #ifdef OCCT_DEBUG
271   Standard_Integer iFI =
272 #endif
273             myPBDS->Shape(FI);
274 //    myPBDS->Shape(FT);
275
276 #ifdef OCCT_DEBUG
277   Standard_Boolean TRCFI = FTRCF(iFI);if (TRCFI) debredfac(iFI);
278 #endif
279
280   if (!E.IsSame(myEdge)) {FUN_RaiseError();return;}
281
282   if (!myrefdef) { 
283     Init(FI,E,EEisnew,I); // premiere interference sur face orientee : Init
284     return;
285   }
286
287 #ifdef OCCT_DEBUG
288 //  TopAbs_Orientation FTori = FT.Orientation();
289 #endif
290   TopOpeBRepDS_Kind GT,ST; Standard_Integer G,S; FDS_data(I,GT,G,ST,S);
291 #ifdef OCCT_DEBUG
292 //  Standard_Boolean gisb = I->GBound(); 
293 #endif
294   const TopoDS_Edge& EG = TopoDS::Edge(myPBDS->Shape(G));
295 #ifdef OCCT_DEBUG
296 //  Standard_Boolean ghassd3d =
297 #endif
298                  FDS_HasSameDomain3d(*myPBDS,EG);
299 #ifdef OCCT_DEBUG
300 //  Standard_Integer gr = myPBDS->SameDomainRef(G);
301 //  const TopoDS_Edge& ER = TopoDS::Edge(myPBDS->Shape(gr));
302 //  Standard_Integer gisr = (G == gr);
303 #endif
304   Standard_Boolean same = !STATIC_TOREVERSE; // xpu150498
305   
306   TopAbs_Orientation oriloc = I->Transition().Orientation(TopAbs_IN);
307   // xpu150498 : CTS20205 : sp(e5) = sp(e4 of rank=1) and c3d(e5) c3d(e4) are diff oriented
308   //            As transitions on face<iFI> are given relative to the geometry of e5,
309   //            we have to complement them.
310   //             cto 016 E1
311   Standard_Boolean rev = !same && (M_FORWARD(oriloc) || M_REVERSED(oriloc)); //xpu150498 
312   if (rev) oriloc = TopAbs::Complement(oriloc); //xpu150498 
313
314   TopAbs_Orientation oritan;
315   TopAbs_Orientation oriEFT; Standard_Boolean egofft = FUN_tool_orientEinFFORWARD(EG,FT,oriEFT);
316   TopAbs_Orientation oriEFI; Standard_Boolean egoffi = FUN_tool_orientEinFFORWARD(EG,FI,oriEFI);
317   if      (egofft) {
318     oritan = oriEFT;    
319     if (EEisnew && !same) oritan = TopAbs::Complement(oriEFT);
320   }
321   else if (egoffi) {
322     oritan = oriEFI;    
323     if (EEisnew && !same) oritan = TopAbs::Complement(oriEFI);
324   }
325   else { FUN_RaiseError(); return; }
326
327   gp_Pnt2d uv; Standard_Boolean ok = Standard_False;
328   if (egofft) ok = FUN_tool_paronEF(E,myParOnEd,FT,uv);
329   if (!ok) {Standard_Real d; ok = FUN_tool_projPonF(myPntOnEd,FT,uv,d);}
330   if (!ok) { FUN_RaiseError(); return;}
331
332   gp_Dir Norm;
333   if(isLine) {
334     FUN_ComputeGeomData(FT,uv,Norm);
335 //    if (Fori == TopAbs_REVERSED) Norm.Reverse();
336     myTool.Compare(myTole,Norm,oriloc,oritan);
337   }
338   else {
339     gp_Dir D1,D2; Standard_Real Cur1,Cur2;
340     FUN_ComputeGeomData(FT,uv,Norm,D1,D2,Cur1,Cur2);
341 //    if (Fori == TopAbs_REVERSED) Norm.Reverse();
342     myTool.Compare(myTole,Norm,D1,D2,Cur1,Cur2,oriloc,oritan); 
343   }  
344 }
345
346 //=======================================================================
347 //function : Add
348 //purpose  :
349 //=======================================================================
350 void TopOpeBRepDS_FaceInterferenceTool::Add
351 //(const TopoDS_Shape& F,const TopOpeBRepDS_Curve& C,const Handle(TopOpeBRepDS_Interference)& I)
352 (const TopoDS_Shape& ,const TopOpeBRepDS_Curve& ,const Handle(TopOpeBRepDS_Interference)& )
353 {
354   // NYI
355 }
356
357 //=======================================================================
358 //function : Transition
359 //purpose  : 
360 //=======================================================================
361 void TopOpeBRepDS_FaceInterferenceTool::Transition(const Handle(TopOpeBRepDS_Interference)& I) const 
362 {
363   TopOpeBRepDS_Transition& T = I->ChangeTransition();
364
365   if (myFaceOrientation == TopAbs_INTERNAL) {
366     T.Set(TopAbs_IN,TopAbs_IN);
367   }
368   else if (myFaceOrientation == TopAbs_EXTERNAL) {
369     T.Set(TopAbs_OUT,TopAbs_OUT);
370   }
371   else {
372     I->Support(myFaceOriented);
373     TopAbs_State stb = myTool.StateBefore();
374     TopAbs_State sta = myTool.StateAfter();
375     T.Set(stb,sta);
376     //xpu150498 
377     TopAbs_Orientation o = T.Orientation(TopAbs_IN);
378     Standard_Boolean rev = STATIC_TOREVERSE && (M_FORWARD(o) || M_REVERSED(o));
379     if (rev) o = TopAbs::Complement(o);
380     T.Set(o);
381     //xpu150498 
382   }
383 }
384
385 //=======================================================================
386 //function : SetEdgePntPar
387 //purpose  : 
388 //=======================================================================
389 void TopOpeBRepDS_FaceInterferenceTool::SetEdgePntPar(const gp_Pnt& P,const Standard_Real p)
390 {
391   myPntOnEd = P;
392   myParOnEd = p;
393   myOnEdDef = Standard_True;
394 }
395
396 //=======================================================================
397 //function : GetEdgePnt
398 //purpose  : 
399 //=======================================================================
400 void TopOpeBRepDS_FaceInterferenceTool::GetEdgePntPar(gp_Pnt& P,Standard_Real& p) const
401 {
402   if (!myOnEdDef) Standard_ProgramError::Raise("GetEdgePntPar");
403   P = myPntOnEd;
404   p = myParOnEd;
405 }
406
407 //=======================================================================
408 //function : IsEdgePnt
409 //purpose  : 
410 //=======================================================================
411
412 Standard_Boolean TopOpeBRepDS_FaceInterferenceTool::IsEdgePntParDef() const
413 {
414   return myOnEdDef;
415 }