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