0024947: Redesign OCCT legacy type system -- automatic
[occt.git] / src / TopOpeBRepDS / TopOpeBRepDS_ProcessFaceInterferences.cxx
1 // Created on: 1997-02-14
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1997-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 <TopoDS.hxx>
18 #include <TopExp.hxx>
19 #include <TopExp_Explorer.hxx>
20 #include <TColStd_DataMapIteratorOfDataMapOfIntegerListOfInteger.hxx>
21 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
22 #include <TColStd_ListIteratorOfListOfInteger.hxx>
23 #include <TColStd_ListOfInteger.hxx>
24 #include <BRepAdaptor_Curve.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepClass3d_SolidClassifier.hxx>
28 #include <TopoDS_Shell.hxx>
29 #include <TopoDS_Solid.hxx>
30 #include <gp_Vec.hxx>
31 #include <Precision.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_Surface.hxx>
34 #include <GeomAPI_ProjectPointOnSurf.hxx>
35 #include <BRepTools.hxx>
36
37 #include <TopOpeBRepTool_ShapeTool.hxx>
38 #include <TopOpeBRepTool_EXPORT.hxx>
39 #include <TopOpeBRepTool_TOOL.hxx>
40
41 #include <TopOpeBRepDS_FaceEdgeInterference.hxx>
42 #include <TopOpeBRepDS_define.hxx>
43 #include <TopOpeBRepDS_ProcessInterferencesTool.hxx>
44 #include <TopOpeBRepDS_FaceEdgeInterference.hxx>
45 #include <TopOpeBRepDS_FaceInterferenceTool.hxx>
46 #include <TopOpeBRepDS_ListOfShapeOn1State.hxx>
47 #include <TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State.hxx>
48 #include <TopOpeBRepTool_ShapeClassifier.hxx>
49 #include <TopOpeBRepTool_PShapeClassifier.hxx>
50 #include <TopOpeBRepDS_ShapeShapeInterference.hxx>
51
52 Standard_EXPORT void FUN_UNKFstasta(const TopoDS_Face& FF,const TopoDS_Face& FS,
53                                     const TopoDS_Edge& EE,const Standard_Boolean EEofFF,
54                                     TopAbs_State& stateb,TopAbs_State& statea,
55                                     TopOpeBRepTool_PShapeClassifier pClassif);
56
57 #define MDShfei Handle(TopOpeBRepDS_FaceEdgeInterference)
58 #define MAKEFEI(IJKLM) (Handle(TopOpeBRepDS_FaceEdgeInterference)::DownCast(IJKLM))
59
60 #ifdef OCCT_DEBUG
61 extern Standard_Boolean TopOpeBRepDS_GetcontextNOPFI();
62 extern Standard_Boolean TopOpeBRepDS_GettracePFI();
63 extern Standard_Boolean TopOpeBRepDS_GettracePI();
64 extern Standard_Boolean TopOpeBRepDS_GettraceSPSX(const Standard_Integer);
65 static Standard_Boolean TRCF(const Standard_Integer F) {
66   Standard_Boolean b1 = TopOpeBRepDS_GettracePFI();
67   Standard_Boolean b2 = TopOpeBRepDS_GettracePI();
68   Standard_Boolean b3 = TopOpeBRepDS_GettraceSPSX(F);
69   return (b1 || b2 || b3);
70 }
71 static void debredunkf(const Standard_Integer /*i*/){};
72 #endif
73
74 Standard_EXPORT Standard_Boolean FUN_Parameters(const gp_Pnt& Pnt,const TopoDS_Shape& F,Standard_Real& u,Standard_Real& v);
75 Standard_EXPORT Standard_Boolean FUN_Parameters(const Standard_Real& Param,const TopoDS_Shape& E,const TopoDS_Shape& F,Standard_Real& u,Standard_Real& v);
76
77 //=======================================================================
78 // 3D
79 // purpose : The compute of transition face <F> /face <FS>,
80 //           or edge <E>
81 // prequesitory : <E> is IN 2dmatter(F) and IN 2dmatter(FS)
82 //=======================================================================
83
84 Standard_EXPORT Standard_Boolean FUN_mkTonF(const TopoDS_Face& F, const TopoDS_Face& FS, const TopoDS_Edge& E, 
85                                TopOpeBRepDS_Transition& T)
86 {
87   Standard_Boolean isdgE = BRep_Tool::Degenerated(E); 
88   if (isdgE) return Standard_False;
89   T.Set(TopAbs_UNKNOWN,TopAbs_UNKNOWN);
90
91   Standard_Real tola = 1.e-6; // nyitol
92   Standard_Real f,l; FUN_tool_bounds(E,f,l);
93   const Standard_Real PAR_T = 0.456789;
94   Standard_Real pmil = (1.-PAR_T)*f + PAR_T*l;
95   gp_Vec tgE; 
96   Standard_Boolean ok; 
97   
98   ok = TopOpeBRepTool_TOOL::TggeomE(pmil,E,tgE);
99   //modified by NIZNHY-PKV Fri Aug  4 10:59:44 2000 f
100   if (!ok) {
101     return Standard_False;
102   }
103     //modified by NIZNHY-PKV Fri Aug  4 10:59:48 2000 t
104   
105   gp_Pnt2d uvF; 
106   ok = FUN_tool_parF(E,pmil,F,uvF);
107   if (!ok) 
108     return Standard_False;
109  
110   gp_Pnt2d uvFS; 
111   ok = FUN_tool_parF(E,pmil,FS,uvFS);
112   if (!ok) 
113     return Standard_False;
114   
115   gp_Dir ngF = FUN_tool_nggeomF(uvF,F);
116   Standard_Real xx = Abs(ngF.Dot(tgE));
117   Standard_Boolean tgt = (Abs(1-xx) < tola);
118   if (tgt) return Standard_False;
119
120   gp_Dir ntFS; 
121   ok = TopOpeBRepTool_TOOL::Nt(uvFS,FS, ntFS);
122   if (!ok) 
123     return Standard_False;
124   gp_Dir beafter = ngF^tgE;
125   Standard_Real yy = beafter.Dot(ntFS);
126   Standard_Boolean unk = (Abs(yy) < tola);
127   if (unk) 
128     return Standard_False;
129
130   if (yy < 0.) T.Set(TopAbs_FORWARD);
131   else         T.Set(TopAbs_REVERSED);
132   return Standard_True;
133 }
134
135
136 //------------------------------------------------------
137 // FUN_edgeofface :  True si le edge E est un edge de F
138 Standard_EXPORT Standard_Boolean FUN_edgeofface
139 //------------------------------------------------------
140 (const TopoDS_Shape& E,const TopoDS_Shape& F)
141 {
142   Standard_Boolean isv = Standard_False;
143   TopExp_Explorer ex;
144   for (ex.Init(F,TopAbs_EDGE); ex.More(); ex.Next())
145 //  for (TopExp_Explorer ex(F,TopAbs_EDGE); ex.More(); ex.Next())
146     if (ex.Current().IsSame(E) ) {
147       isv = Standard_True;
148       break;
149     }
150   return isv;
151 }
152
153 //------------------------------------------------------
154 Standard_EXPORT Standard_Boolean FUN_keepFinterference
155 //------------------------------------------------------
156 (const TopOpeBRepDS_DataStructure& DS,const Handle(TopOpeBRepDS_Interference)& I,const TopoDS_Shape& F)
157 {
158   TopOpeBRepDS_Kind GT1,ST1; Standard_Integer G1,S1; FDS_data(I,GT1,G1,ST1,S1);
159   
160   Standard_Boolean res = Standard_True;
161   if ( I->IsKind(STANDARD_TYPE(TopOpeBRepDS_FaceEdgeInterference)) ) {
162     
163     const TopoDS_Shape& EG = DS.Shape(I->Geometry());
164     // I rejetee si son edge-geometrie est une arete de la face qui accede I.
165     Standard_Boolean k3 = ! ::FUN_edgeofface(EG,F);
166     res = res && k3;
167   }
168   
169   return res;
170 }
171
172 //------------------------------------------------------
173 Standard_EXPORT void FUN_unkeepFdoubleGBoundinterferences
174 //------------------------------------------------------
175 (TopOpeBRepDS_ListOfInterference& LI,const TopOpeBRepDS_DataStructure& /*BDS*/,
176 #ifdef OCCT_DEBUG
177  const Standard_Integer SIX)    
178 #else
179  const Standard_Integer )    
180 #endif
181 {
182 #ifdef OCCT_DEBUG
183   Standard_Boolean TRC=TRCF(SIX);
184 #endif
185 //                 BDS.Shape(SIX);
186   TopOpeBRepDS_ListIteratorOfListOfInterference it1;
187   
188   // process interferences of LI with VERTEX geometry
189   
190   it1.Initialize(LI);
191   while (it1.More() ) {
192     Handle(TopOpeBRepDS_Interference)& I1 = it1.Value();
193     TopOpeBRepDS_Kind GT1,ST1; Standard_Integer G1,S1;
194     const TopOpeBRepDS_Transition& T1 = I1->Transition();
195     Standard_Boolean isunk1 = T1.IsUnknown();
196     if (isunk1) { it1.Next(); continue; }
197
198     FDS_data(I1,GT1,G1,ST1,S1);
199     Handle(TopOpeBRepDS_ShapeShapeInterference) SSI1 = Handle(TopOpeBRepDS_ShapeShapeInterference)::DownCast(I1);
200     if (SSI1.IsNull()) { it1.Next(); continue; }
201
202     Standard_Boolean isB1 = SSI1->GBound();
203     
204     TopOpeBRepDS_ListIteratorOfListOfInterference it2(it1);
205     it2.Next();
206     Standard_Boolean cond1 = Standard_False;    
207     Standard_Boolean cond2 = Standard_False;    
208     
209     while ( it2.More() ) {
210       const Handle(TopOpeBRepDS_Interference)& I2 = it2.Value();
211       TopOpeBRepDS_Kind GT2,ST2; Standard_Integer G2,S2;
212       const TopOpeBRepDS_Transition& T2 = I2->Transition();
213       Standard_Boolean isunk2 = T2.IsUnknown();
214       if (isunk2) { it2.Next(); continue; }
215
216       FDS_data(I2,GT2,G2,ST2,S2);
217       Handle(TopOpeBRepDS_ShapeShapeInterference) SSI2 = Handle(TopOpeBRepDS_ShapeShapeInterference)::DownCast(I2);
218       if ( SSI2.IsNull() ) { it2.Next(); continue; }
219
220       Standard_Boolean isB2 = SSI2->GBound();       
221       cond2 = (GT2 == GT1 && GT1 == TopOpeBRepDS_EDGE && G2 == G1 &&
222                ST2 == ST1 && ST1 == TopOpeBRepDS_FACE && S2 != S1 &&
223                isB1 && isB2);
224       
225       if (cond2) {
226 #ifdef OCCT_DEBUG
227         if(TRC){cout<<"face "<<SIX<<" : G2 "<< G2 <<" GBound ";I2->Dump(cout);cout<<endl;}
228 #endif
229         cond1 = Standard_True;
230         LI.Remove(it2);
231       }
232       else it2.Next();
233     } // it2.More()
234
235     if (cond1) {
236 #ifdef OCCT_DEBUG
237       if(TRC){cout<<"face "<<SIX<<" : G1 "<< G1 <<" GBound ";I1->Dump(cout);cout<<endl;}
238 #endif
239       LI.Remove(it1);
240     }
241     else it1.Next();
242   } // it1.More()
243
244 } // FUN_unkeepFdoubleGBoundinterferences
245
246 //------------------------------------------------------
247 Standard_EXPORT void FUN_resolveFUNKNOWN
248 //------------------------------------------------------
249 (TopOpeBRepDS_ListOfInterference& LI,TopOpeBRepDS_DataStructure& BDS,
250  const Standard_Integer SIX,
251  const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State& MEsp,
252  TopOpeBRepTool_PShapeClassifier pClassif)
253 {
254 #ifdef OCCT_DEBUG
255   Standard_Boolean TRC=TRCF(SIX); if (TRC) debredunkf(SIX);
256   Standard_Boolean modif = Standard_False;
257 #endif
258
259   const TopoDS_Shape& F = BDS.Shape(SIX);
260   TopOpeBRepDS_ListIteratorOfListOfInterference it1;
261   
262   const TopoDS_Face& FF = TopoDS::Face(F);
263 //  Standard_Real fE,lE; BRep_Tool::Range(EE,fE,lE);
264   
265   // process interferences of LI with UNKNOWN transition
266   
267   for (it1.Initialize(LI); it1.More(); it1.Next() ) {
268     Handle(TopOpeBRepDS_Interference)& I1 = it1.Value();
269     const TopOpeBRepDS_Transition& T1 = I1->Transition();
270     Standard_Boolean isunk = T1.IsUnknown();
271     if (!isunk) continue;
272
273 #ifdef OCCT_DEBUG
274     modif = Standard_True;
275     if(TRC){debredunkf(SIX);TCollection_AsciiString s="F";s=s+SIX+" T UNKNOWN ";I1->Dump(cout,s,"\n");}
276 #endif
277     
278     TopOpeBRepDS_Kind GT1,ST1; Standard_Integer G1,S1; TopAbs_ShapeEnum tsb1,tsa1; Standard_Integer isb1,isa1; 
279     FDS_Idata(I1,tsb1,isb1,tsa1,isa1,GT1,G1,ST1,S1);
280     Standard_Boolean idt = (tsb1==TopAbs_FACE && tsa1==TopAbs_FACE 
281                && GT1==TopOpeBRepDS_EDGE && ST1==TopOpeBRepDS_FACE);
282     Standard_Boolean idi = (isb1==S1 && isa1==S1);
283     Standard_Boolean etgf = idt && idi; // face tangent a une face en 1 edge
284     if (!etgf) continue;
285
286     const TopoDS_Edge& EE = TopoDS::Edge(BDS.Shape(G1));
287     Standard_Real fE,lE; BRep_Tool::Range(EE,fE,lE);
288     
289 #ifdef OCCT_DEBUG
290     if(TRC){debredunkf(SIX);TCollection_AsciiString s="F";s=s+SIX+" etgf ";I1->Dump(cout,s,"\n");}
291 #endif
292
293     Handle(TopOpeBRepDS_FaceEdgeInterference) fei = MAKEFEI(I1);
294     if (fei.IsNull()) continue;
295
296     const TopoDS_Face& FS = TopoDS::Face(BDS.Shape(S1));
297
298 //    if (!go) continue;
299
300     // la face FF transitionne par la transition T1.IsUnknown()
301     // en l'arete EE par rapport a la face FS.
302     // range de EE = [fE,lE].
303     // EE est une arete de FF ou non.
304     // EE est une arete de section.
305     // EE est une arete de couture.
306     Standard_Boolean isEEGB = fei->GBound();
307     Standard_Boolean isEEsp = MEsp.IsBound(EE);
308     TopoDS_Edge EEsp = EE;
309     if (isEEsp) {
310       const TopOpeBRepDS_ListOfShapeOn1State& los1 = MEsp.Find(EE);
311       isEEsp = los1.IsSplit();
312       if (isEEsp) {
313         const TopTools_ListOfShape& los = los1.ListOnState();
314         Standard_Integer n = los.Extent();
315         if ( n ) {
316           EEsp = TopoDS::Edge(los.First());
317           if (!EEsp.IsSame(EE)) isEEGB = Standard_False;
318           if (n > 1) {
319             // MSV: treat the case of multiple splits:
320             //      select the split which lies on both faces
321             TopTools_ListIteratorOfListOfShape it(los);
322             for (; it.More(); it.Next()) {
323               const TopoDS_Edge& aE = TopoDS::Edge(it.Value());
324               Standard_Real f,l; FUN_tool_bounds(aE,f,l);
325               const Standard_Real PAR_T = 0.456789;
326               Standard_Real pmil = (1.-PAR_T)*f + PAR_T*l;
327               gp_Pnt2d uvF; 
328               if (FUN_tool_parF(aE,pmil,FF,uvF) && FUN_tool_parF(aE,pmil,FS,uvF)) {
329                 EEsp = aE;
330                 break;
331               }
332             }
333           }
334         }
335       }
336     }
337     Standard_Boolean isSO = Standard_True;
338     if (!EEsp.IsSame(EE))
339       if (!FUN_tool_curvesSO(EEsp,EE,isSO)) continue;
340
341     TopAbs_State stateb,statea;     
342     TopOpeBRepDS_Transition T; Standard_Boolean ok = FUN_mkTonF(FF,FS,EEsp,T); //xpu230498
343     if (ok) {stateb = T.Before(); statea =T.After();} //xpu230498
344     else {
345       TopOpeBRepTool_PShapeClassifier pClass = 0;
346       if (pClassif) {
347         // MSV: find Solids of the same object rank as FS
348         //      to determine transition relatively solid rather then face
349         //      if possible (see pb. in CFE002 C2, when SIX==13)
350         Standard_Integer rankFS = BDS.AncestorRank(S1);
351         TopoDS_Shape aSRef = BDS.Shape(rankFS);
352         TopExp_Explorer ex(aSRef,TopAbs_SOLID);
353         if (ex.More()) {
354           pClass = pClassif;
355           pClass->SetReference(aSRef);
356         }
357       }
358       FUN_UNKFstasta(FF,FS,EEsp,isEEGB,stateb,statea,pClass);
359     }
360     if (stateb==TopAbs_UNKNOWN || statea==TopAbs_UNKNOWN) continue;
361
362     TopOpeBRepDS_Transition& newT1 = I1->ChangeTransition();
363     if (!isSO) {
364       TopAbs_State stmp = stateb; stateb = statea; statea = stmp;
365     }
366     newT1.Set(stateb,statea,tsb1,tsa1);
367
368 #ifdef OCCT_DEBUG
369     if(TRC){debredunkf(SIX);TCollection_AsciiString s="F";s=s+SIX+" T corrected ";I1->Dump(cout,s,"\n");}
370 #endif
371
372   }
373
374 #ifdef OCCT_DEBUG
375   if(TRC && modif){ FDS_dumpLI(LI,"apres correction UNKNOWN : "); }
376 #endif  
377
378   FUN_unkeepUNKNOWN(LI,BDS,SIX);
379   
380 #ifdef OCCT_DEBUG
381   if(TRC && modif){ FDS_dumpLI(LI,"sans suppression UNKNOWN residuels : "); }
382 #endif  
383 }
384
385 //========================== DEB start
386 #ifdef OCCT_DEBUG
387 //Standard_IMPORT void FUN_ComputeGeomData(const TopoDS_Shape& F,const Standard_Real& u,const Standard_Real& v,gp_Dir& Norm);
388 //------------------------------------------------------
389 // Automatic testing for complex faces interference on line with cylinders and planes xpu NYI: general case
390 //------------------------------------------------------
391 Standard_Boolean TestTransition(const TopOpeBRepDS_Transition& T,const TopoDS_Face& F,const TopoDS_Edge& E,const TopoDS_Solid& So) // DEB only
392 {
393   TopAbs_State b, a;
394   b = T.Before(); a = T.After();
395   
396   BRepAdaptor_Curve ac(E);
397   GeomAbs_CurveType ctyp = ac.GetType();
398   //  TCollection_AsciiString nt; TestTopOpeDraw_TTOT::CurveToString(ctyp,nt);
399   if (ctyp != GeomAbs_Line) {
400     //    cout << " Case "<<nt;
401     cout <<" not treated"<<endl;
402     return Standard_True;
403   }
404   BRepAdaptor_Surface as(F);
405   GeomAbs_SurfaceType styp = as.GetType();
406   //  TestTopOpeDraw_TTOT::CurveToString(styp,nt);
407   if (!((styp == GeomAbs_Plane)||(styp == GeomAbs_Cylinder))) {
408     //    cout << " Case "<<nt;
409     cout<<" not treated"<<endl;
410     return Standard_True;
411   }
412   Standard_Real du = TopOpeBRepTool_ShapeTool::Tolerance(E); du *= 5.; // edge tolerance
413   Standard_Real u, v, up, vp, p = (ac.FirstParameter() + ac.LastParameter())*.5;
414   gp_Pnt pnt, pntnorm; // middle point on edge
415   gp_Vec tgt, beafter; // curve tangent vector at pnt
416   gp_Dir normS; // normal and direction (Before, After) on reference surface.
417   
418   ac.D1(p, pnt, tgt);
419   Standard_Boolean prodone = FUN_Parameters(pnt, F, u, v); // DEB u, v pntnorm coordinates on F
420   if (!prodone){
421     cout<<" not treated : prendre un point sur le common des aretes de section SDM"<<endl;
422     return Standard_True;
423   }
424 #ifdef OCCT_DEBUG
425 //  FUN_ComputeGeomData (F, u, v, normS);
426 #endif
427   normS = FUN_tool_nggeomF(gp_Pnt2d(u,v), F); 
428   beafter  = normS^gp_Vec(tgt); beafter.Scale(du); // beafter of length du
429   pntnorm = gp_Pnt(pnt.XYZ()).Translated(beafter); // (pnt, pntnorm) = du*beafter
430   FUN_Parameters(pntnorm, F, up, vp); // DEB up, vp pntnorm coordinates on F
431   
432   gp_Pnt pAfter, pBefore;
433   as.D0(up, vp, pAfter);
434   as.D0(up-2*(up-u), vp -2*(vp-v), pBefore);
435   
436   Standard_Boolean transok;
437   TopAbs_State stb, sta;
438   BRepClass3d_SolidClassifier classif(So);
439   
440   classif.Perform(pBefore, Precision::Confusion()); stb = classif.State();  
441   classif.Perform(pAfter, Precision::Confusion()); sta = classif.State();
442   transok = (stb == b)&&(sta == a);
443   
444   if(!transok) {
445     cout<<"States found by classifier :"<<endl;
446         cout << "Before  :";
447         TopAbs::Print(stb, cout);
448         cout << "After  :";
449         TopAbs::Print(sta, cout);
450         cout << endl;
451   }
452   
453   return transok;
454 }
455
456 #endif
457 //========================== DEB end 
458