0027067: Avoid use of virtual methods for implementation of destructors in legacy...
[occt.git] / src / TopOpeBRepBuild / TopOpeBRepBuild_WireEdgeClassifier.cxx
1 // Created on: 1993-06-17
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1993-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
18 #include <TopoDS_Shape.hxx>
19 #include <TopOpeBRepBuild_BlockBuilder.hxx>
20 #include <TopOpeBRepBuild_Loop.hxx>
21 #include <TopOpeBRepBuild_WireEdgeClassifier.hxx>
22
23 #ifdef DRAW
24 #include <DBRep.hxx>
25 #endif
26
27 #include <Precision.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Wire.hxx>
32 #include <TopoDS_Face.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <BRep_Tool.hxx>
35 #include <Geom2d_Curve.hxx>
36 #include <BRepClass_FaceClassifier.hxx>
37 #include <Standard_ProgramError.hxx>
38 #include <Geom_Curve.hxx>
39 #include <Geom_TrimmedCurve.hxx>
40 #include <gp_Pnt.hxx>
41 #include <gp_Vec2d.hxx>
42 #include <BRep_Builder.hxx>
43 #include <TopOpeBRepTool_2d.hxx>
44 #include <TopLoc_Location.hxx>
45 #include <TopExp.hxx>
46
47 #include <TopOpeBRepTool_EXPORT.hxx>
48 #include <TopOpeBRepTool_SC.hxx>
49 #include <TopOpeBRepTool_TOOL.hxx>
50 #include <TopOpeBRepTool_CurveTool.hxx>
51
52 #include <TopOpeBRepBuild_Builder.hxx>
53 #include <TopOpeBRepBuild_define.hxx>
54
55 #ifdef OCCT_DEBUG
56 #define TSTRA TopOpeBRepDS_GettraceSTRANGE()
57 static TCollection_AsciiString PRODINS("dins ");
58 extern Standard_Boolean TopOpeBRepDS_GettraceSTRANGE();
59 #endif
60
61 //Standard_IMPORT extern TopOpeBRepBuild_Builder* GLOBAL_PBUILDER;
62 Standard_IMPORT TopOpeBRepBuild_Builder* GLOBAL_PBUILDER;
63 #define MYBB ((TopOpeBRepBuild_BlockBuilder*)myBlockBuilder)
64
65
66 #define SAME     (-1)
67 #define DIFF     (-2)
68 #define UNKNOWN  ( 0)
69 #define oneINtwo ( 1)
70 #define twoINone ( 2)
71
72 //=======================================================================
73 //function : TopOpeBRepBuild_WireEdgeClassifier
74 //purpose  : 
75 //=======================================================================
76
77 TopOpeBRepBuild_WireEdgeClassifier::TopOpeBRepBuild_WireEdgeClassifier
78 (const TopoDS_Shape& F,
79  const TopOpeBRepBuild_BlockBuilder& BB) :
80 TopOpeBRepBuild_CompositeClassifier(BB)
81 {
82   myBCEdge.Face() = TopoDS::Face(F);
83 }
84
85 //=======================================================================
86 //function : Compare
87 //purpose  : 
88 //=======================================================================
89
90 TopAbs_State TopOpeBRepBuild_WireEdgeClassifier::Compare
91 (const Handle(TopOpeBRepBuild_Loop)& L1,
92  const Handle(TopOpeBRepBuild_Loop)& L2)
93
94   TopAbs_State state = TopAbs_UNKNOWN;
95
96   Standard_Boolean isshape1 = L1->IsShape();
97   Standard_Boolean isshape2 = L2->IsShape();
98
99   if      ( isshape2 && isshape1 )  { // L1 is Shape , L2 is Shape
100     const TopoDS_Shape& s1 = L1->Shape();
101     const TopoDS_Shape& s2 = L2->Shape();
102     state = CompareShapes(s1,s2);
103   }
104   else if ( isshape2 && !isshape1 ) { // L1 is Block , L2 is Shape
105     TopOpeBRepBuild_BlockIterator Bit1 = L1->BlockIterator();
106     Bit1.Initialize();
107     Standard_Boolean yena1 = Bit1.More();
108     while (yena1) {
109       const TopoDS_Shape& s1 = MYBB->Element(Bit1);
110       const TopoDS_Shape& s2 = L2->Shape();
111       state = CompareElementToShape(s1,s2);
112       yena1 = Standard_False;
113       if (state == TopAbs_UNKNOWN) { 
114         if (Bit1.More()) Bit1.Next();
115         yena1 = Bit1.More();
116       }
117     }
118   }
119   else if ( !isshape2 && isshape1 ) { // L1 is Shape , L2 is Block
120     const TopoDS_Shape& s1 = L1->Shape();
121     ResetShape(s1);
122     TopOpeBRepBuild_BlockIterator Bit2 = L2->BlockIterator();
123     for (Bit2.Initialize(); Bit2.More(); Bit2.Next()) {
124       const TopoDS_Shape& s2 = MYBB->Element(Bit2);
125       CompareElement(s2);
126     }
127     state = State();
128   }
129   else if ( !isshape2 && !isshape1 ) { // L1 is Block , L2 is Block
130
131     if (state == TopAbs_UNKNOWN) {      
132       TopOpeBRepBuild_BlockIterator Bit1 = L1->BlockIterator();
133       Bit1.Initialize();
134       Standard_Boolean yena1 = Bit1.More();
135       while (yena1) {
136         const TopoDS_Shape& s1 = MYBB->Element(Bit1);
137         ResetElement(s1);
138         TopOpeBRepBuild_BlockIterator Bit2 = L2->BlockIterator();
139         for (Bit2.Initialize(); Bit2.More(); Bit2.Next()) {
140           const TopoDS_Shape& s2 = MYBB->Element(Bit2);
141           CompareElement(s2);
142         }
143         state = State();
144         yena1 = Standard_False;
145         if (state == TopAbs_UNKNOWN) { 
146           if (Bit1.More()) Bit1.Next();
147           yena1 = Bit1.More();
148         }
149       }
150     } //UNKNOWN
151
152     if (state == TopAbs_UNKNOWN) {
153 #ifdef OCCT_DEBUG
154       if (TSTRA) cout<<"TopOpeBRepBuild_Builder::WES::Compare UNKNOWN -> ShapeClassifier "<<endl;
155 #endif
156     }
157
158     if (state == TopAbs_UNKNOWN) {
159       TopoDS_Shape s1 = LoopToShape(L1); if (s1.IsNull()) return state;
160       TopoDS_Shape s2 = LoopToShape(L2); if (s2.IsNull()) return state;
161       TopOpeBRepTool_ShapeClassifier& SC = FSC_GetPSC();
162       Standard_Integer samedomain = SC.SameDomain(); SC.SameDomain(1); 
163       SC.SetReference(s2);
164       const TopoDS_Shape& AvS = s2;
165       state = SC.StateShapeReference(s1,AvS);
166       SC.SameDomain(samedomain);
167     } // UNKNOWN
168
169   }
170   return state;
171 }
172
173 //=======================================================================
174 //function : LoopToShape
175 //purpose  : 
176 //=======================================================================
177
178 TopoDS_Shape TopOpeBRepBuild_WireEdgeClassifier::LoopToShape(const Handle(TopOpeBRepBuild_Loop)& L)
179 {
180   myShape.Nullify();
181   TopOpeBRepBuild_BlockIterator Bit = L->BlockIterator();
182   Bit.Initialize();
183   if ( !Bit.More() ) return myShape;
184
185   TopoDS_Shape aLocalShape = myBCEdge.Face();
186   const TopoDS_Face& F1 = TopoDS::Face(aLocalShape);
187 //  const TopoDS_Face& F1 = TopoDS::Face(myBCEdge.Face());
188   aLocalShape = F1.EmptyCopied();
189   TopoDS_Face F = TopoDS::Face(aLocalShape);
190 //  TopoDS_Face F = TopoDS::Face(F1.EmptyCopied());
191   BRep_Builder BB; TopoDS_Wire W; BB.MakeWire(W);
192   for  (; Bit.More(); Bit.Next()) {
193     const TopoDS_Edge& E = TopoDS::Edge(MYBB->Element(Bit));
194     Standard_Real tolE; tolE = BRep_Tool::Tolerance(E);
195     Standard_Boolean haspc = FC2D_HasCurveOnSurface(E,F);
196     if (!haspc) {
197       Standard_Real f,l,tolpc;Handle(Geom2d_Curve) C2D;
198       C2D = FC2D_CurveOnSurface(E,F,f,l,tolpc);
199       if (!C2D.IsNull()) {
200         Standard_Real tol = Max(tolpc,tolE);
201         BB.UpdateEdge(E,C2D,F,tol);
202       }
203     }
204     BB.Add(W,E);
205   }
206   BB.Add(F,W);
207
208   myShape = F;
209   return myShape;
210 }
211
212 static gp_Vec FUN_tgINE(const TopoDS_Vertex& v, const TopoDS_Vertex& vl, const TopoDS_Edge& e)
213 // tg oriented INSIDE 1d(e)
214 // vl : last vertex of e
215 {
216   Standard_Real par = BRep_Tool::Parameter(v,e);  
217   gp_Vec tg; Standard_Boolean ok = TopOpeBRepTool_TOOL::TggeomE(par,e,tg);
218   if (!ok) return gp_Vec(0.,0.,0.); //NYIRAISE
219   if (v.IsSame(vl)) tg.Reverse();
220   return tg;
221 }
222
223 //=======================================================================
224 //function : CompareShapes
225 //purpose  : 
226 //=======================================================================
227
228 TopAbs_State  TopOpeBRepBuild_WireEdgeClassifier::CompareShapes
229 (const TopoDS_Shape& B1, const TopoDS_Shape& B2)
230 {
231   // evolution xpu101198 : - cto009K4, regularisation de f24, 
232   // on classifie 1 wire / 1 des wires connexes.
233   // (face rectangulaire - face circulaire tangente aux bords) - 
234   // WEC completement aleatoire : depend du choix de e1 dans le cas
235   // ou e1 est tangent a E. - e1 droite touche l'autre wire -
236   // on fait l'hypothese que les shapes B1 et B2 proviennent du meme shape,
237   // et que si ils ne se touchent pas, on ne passe pas par le WEC.
238   // INCOMPLET!!!
239
240 #ifdef OCCT_DEBUG
241 //  TopAbs_ShapeEnum t1 = B1.ShapeType();
242 //  TopAbs_ShapeEnum t2 = B2.ShapeType();
243 #endif
244   TopAbs_State state = TopAbs_UNKNOWN;
245   TopExp_Explorer ex1(B1,TopAbs_EDGE);
246   if ( !ex1.More() ) return state;
247   for ( ; ex1.More(); ex1.Next() ) {
248     const TopoDS_Edge& e1 = TopoDS::Edge(ex1.Current());
249     TopoDS_Vertex vf1,vl1; TopExp::Vertices(e1,vf1,vl1);//xpu101198
250     Standard_Boolean e1clo = vf1.IsSame(vl1);
251     TopTools_IndexedMapOfShape mapv1; mapv1.Add(vf1); mapv1.Add(vl1);
252     
253     ResetShape(e1);
254     Standard_Integer iE = 0; Standard_Boolean indy = Standard_False;
255     TopExp_Explorer Ex;
256     for(Ex.Init(B2,TopAbs_EDGE); Ex.More(); Ex.Next()) {
257 //    for(TopExp_Explorer Ex(B2,TopAbs_EDGE); Ex.More(); Ex.Next()) {
258       const TopoDS_Edge& E = TopoDS::Edge(Ex.Current());
259       if (E.IsSame(e1)) { state = TopAbs_UNKNOWN; break; } // eap occ416
260       TopoDS_Vertex vf,vl; TopExp::Vertices(E,vf,vl);//xpu101198
261       Standard_Boolean Eclo = vf.IsSame(vl);//xpu101198
262       Standard_Boolean hasf = mapv1.Contains(vf);//xpu101198
263       Standard_Boolean hasl = mapv1.Contains(vl);//xpu101198     
264       Standard_Boolean filter = (hasf || hasl) && (!e1clo) && (!Eclo);// nyi : Eclo || e1clo
265       if (filter) {//xpu101198
266         TopoDS_Vertex vshared; if (hasf) vshared=vf; if (hasl) vshared=vl;
267         gp_Vec tg1 = FUN_tgINE(vshared,vl1,e1);
268         gp_Vec tg = FUN_tgINE(vshared,vl,E);
269         Standard_Real dot = tg1.Dot(tg);
270         Standard_Real tol = Precision::Angular()*1.e4; // nyixpu
271         Standard_Boolean undecided = (Abs(1+dot) < tol);
272         if (undecided) {indy = Standard_True;}
273       }//xpu101198
274       if (indy) {state = TopAbs_UNKNOWN; break;}
275       CompareElement(E);
276       state = State();
277       iE++;
278     } // ex(B2,EDGE)    
279     if (state != TopAbs_UNKNOWN) {   
280       break;
281     }
282   }// ex1
283   
284   Standard_Boolean resta = (state == TopAbs_UNKNOWN);
285   resta = resta && (B2.ShapeType()==TopAbs_WIRE) && (B1.ShapeType()==TopAbs_WIRE);
286   if (resta) {
287     TopTools_IndexedMapOfShape mape1; TopExp::MapShapes(B1,TopAbs_EDGE,mape1);
288     // recall : avoid auto-intersection wires (ie B1 and B2 are disjoint)
289     TopExp_Explorer ex2(B2,TopAbs_EDGE);
290     for (; ex2.More(); ex2.Next()){
291       const TopoDS_Edge& E2 = TopoDS::Edge(ex2.Current());
292       if (mape1.Contains(E2)) continue;
293       
294       const TopoDS_Face& theFace =  myBCEdge.Face();
295       BRep_Builder BB; 
296
297       // p2d on E2 of B2, E2 not shared by B1
298       TopoDS_Shape aLocalShape = theFace.Oriented(TopAbs_FORWARD);
299       TopoDS_Face ftmp = TopoDS::Face(aLocalShape);
300 //      TopoDS_Face ftmp = TopoDS::Face(theFace.Oriented(TopAbs_FORWARD));
301       aLocalShape = ftmp.EmptyCopied();
302       TopoDS_Face F2 = TopoDS::Face(aLocalShape);
303 //      TopoDS_Face F2 = TopoDS::Face(ftmp.EmptyCopied());
304       BB.Add(F2,TopoDS::Wire(B2));
305
306       BRepAdaptor_Curve2d BC2d(E2,F2); 
307       Standard_Real f,l; FUN_tool_bounds(E2,f,l); Standard_Real x = 0.45678; Standard_Real p2 = (1-x)*l + x*f;
308       gp_Pnt2d p2d = BC2d.Value(p2);
309       
310       aLocalShape = ftmp.EmptyCopied();
311       TopoDS_Face F1 = TopoDS::Face(aLocalShape);
312 //      TopoDS_Face F1 = TopoDS::Face(ftmp.EmptyCopied());
313       BB.Add(F1,TopoDS::Wire(B1));
314
315       Standard_Real tolF1 = BRep_Tool::Tolerance(F1);
316       BRepClass_FaceClassifier Fclass(F1, p2d, tolF1);
317       state = Fclass.State();
318       return state;
319     } // ex2    
320   }
321
322   /*if (state == TopAbs_UNKNOWN) {
323     const TopoDS_Face& F = TopoDS::Face(myBCEdge.Face());
324     Bnd_Array1OfBox2d bnd(1,2);
325     FUN_tool_mkBnd2d(B1,F,bnd(1)); FUN_tool_mkBnd2d(B2,F,bnd(2));
326     TopTools_Array1OfShape B(1,2);
327     B(1)=B1; B(2)=B2;
328 //    Standard_Boolean chklarge=Standard_True; Standard_Integer isma = 0; TopAbs_State osta = FUN_tool_classiBnd2d(bnd,isma,chklarge);
329 //    if (osta == TopAbs_OUT) return TopAbs_OUT;
330 //    if (osta == TopAbs_IN) {
331 //      if (isma == 2) return TopAbs_IN;  //B2 is IN B1 
332 //      else           return TopAbs_OUT; //B2 is OUT B1 (contains B1)  
333 //    }     
334     Standard_Boolean chklarge=Standard_True; Standard_Integer sta = FUN_tool_classiBnd2d(bnd,chklarge);
335     if ((sta == SAME)||(sta == UNKNOWN)) sta = FUN_tool_classiwithp2d(B);
336     if ((sta == SAME)||(sta == UNKNOWN)) return TopAbs_UNKNOWN;  
337     if (sta == DIFF) return TopAbs_OUT; // B1 OUT B2     
338     Standard_Integer isma = (sta == oneINtwo) ? 1 : 2; 
339     if (isma == 2)   return TopAbs_IN;  //B2 is IN B1 
340     else             return TopAbs_OUT; //B2 is OUT B1 (contains B1) 
341   }*/
342   return state;
343 }
344
345
346 //=======================================================================
347 //function : CompareElementToShape
348 //purpose  : 
349 //=======================================================================
350
351 TopAbs_State  TopOpeBRepBuild_WireEdgeClassifier::CompareElementToShape
352 (const TopoDS_Shape& EE,const TopoDS_Shape& B)
353 {
354   // isEdge : edge E inits myPoint2d 
355   ResetElement(EE);
356   TopExp_Explorer Ex;
357   for(Ex.Init(B,TopAbs_EDGE); Ex.More(); Ex.Next()) {
358     const TopoDS_Shape& E = Ex.Current();
359     CompareElement(E);
360   }
361   TopAbs_State state = State();
362   return state;
363 }
364
365
366 //=======================================================================
367 //function : ResetShape
368 //purpose  : 
369 //=======================================================================
370
371 void  TopOpeBRepBuild_WireEdgeClassifier::ResetShape(const TopoDS_Shape& B)
372 {
373   if (B.ShapeType() == TopAbs_EDGE) {
374     ResetElement(B);
375   }
376   else {
377     TopExp_Explorer ex(B,TopAbs_EDGE);
378     if (ex.More())  {
379       const TopoDS_Shape& E = ex.Current();
380       ResetElement(E);
381     }
382   }
383 }
384
385 //=======================================================================
386 //function : ResetElement
387 //purpose  : 
388 //=======================================================================
389
390 void  TopOpeBRepBuild_WireEdgeClassifier::ResetElement(const TopoDS_Shape& EE)
391 {
392   const TopoDS_Edge& E = TopoDS::Edge(EE);
393   const TopoDS_Face& F = myBCEdge.Face();
394   Standard_Real f2,l2,tolpc;Handle(Geom2d_Curve) C2D; //jyl980406+
395   Standard_Boolean haspc = FC2D_HasCurveOnSurface(E,F); //jyl980406+
396   if (!haspc) { //jyl980406+
397     Standard_Boolean trim3d = Standard_True; C2D = FC2D_CurveOnSurface(E,F,f2,l2,tolpc,trim3d); //jyl980406+
398     Standard_Real tolE = BRep_Tool::Tolerance(E); //jyl980406+  
399     Standard_Real tol = Max(tolE,tolpc); //jyl980406+
400     BRep_Builder BB; BB.UpdateEdge(E,C2D,F,tol); //jyl980406+
401   } //jyl980406+
402   
403   C2D = FC2D_CurveOnSurface(E,F,f2,l2,tolpc);
404   if (C2D.IsNull()) Standard_ProgramError::Raise("WEC : ResetElement");
405
406   Standard_Real t = 0.397891143689; Standard_Real par = ((1-t)*f2 + t*l2);
407   myPoint2d = C2D->Value(par);
408   
409 #ifdef OCCT_DEBUG
410   Standard_Real f3,l3; Handle(Geom_Curve) C3D = BRep_Tool::Curve(E,f3,l3);
411   gp_Pnt P3D; if (!C3D.IsNull()) P3D = C3D->Value(par);
412 #endif
413   
414   myFirstCompare = Standard_True;
415 }
416
417
418 //=======================================================================
419 //function : CompareElement
420 //purpose  : 
421 //=======================================================================
422
423 Standard_Boolean TopOpeBRepBuild_WireEdgeClassifier::CompareElement(const TopoDS_Shape& EE)
424 {
425   Standard_Boolean bRet = Standard_True;
426   const TopoDS_Edge& E = TopoDS::Edge(EE);
427   const TopoDS_Face& F = myBCEdge.Face();
428
429   Standard_Real f2,l2,tolpc;Handle(Geom2d_Curve) C2D; //jyl980402+
430   Standard_Boolean haspc = FC2D_HasCurveOnSurface(E,F); //jyl980402+
431   if (!haspc) { //jyl980402+
432     Standard_Boolean trim3d = Standard_True; C2D = FC2D_CurveOnSurface(E,F,f2,l2,tolpc,trim3d); //jyl980406+
433     // C2D = FC2D_CurveOnSurface(E,F,f2,l2,tolpc,trim3d); //jyl980406-
434     Standard_Real tolE = BRep_Tool::Tolerance(E); //jyl980402+  
435     Standard_Real tol = Max(tolE,tolpc); //jyl980402+
436     BRep_Builder BB; BB.UpdateEdge(E,C2D,F,tol); //jyl980402+
437   } //jyl980402+
438
439   if (myFirstCompare) {
440     C2D = FC2D_CurveOnSurface(E,F,f2,l2,tolpc);
441     Standard_Real t = 0.33334567; Standard_Real par = ((1-t)*f2 + t*l2);
442     gp_Pnt2d p2d = C2D->Value(par);
443     
444 #ifdef OCCT_DEBUG
445     Standard_Real f3,l3; Handle(Geom_Curve) C3D = BRep_Tool::Curve(E,f3,l3);
446     gp_Pnt P3D; if (!C3D.IsNull()) P3D = C3D->Value(par);
447 #endif
448     
449     // NYI : p2d peut etre un point ou la courbe n'est pas C1.
450     // NYI : voir TopOpeBRepTool_ShapeClassifier_FindAPointInTheFace
451     gp_Vec2d v2d(myPoint2d,p2d);
452     gp_Lin2d l2d(myPoint2d,v2d);
453     Standard_Real dist = myPoint2d.Distance(p2d);
454     Standard_Real tol2d = Precision::PConfusion(); // NYI : a voir
455     myFPC.Reset(l2d,dist,tol2d);
456     myFirstCompare = Standard_False;
457   }
458   
459   myBCEdge.Edge() = E;
460   TopAbs_Orientation Eori = E.Orientation();
461   myFPC.Compare(myBCEdge,Eori);
462 #ifdef OCCT_DEBUG
463 //  TopAbs_State state = myFPC.State();
464 #endif
465   return bRet;
466 }
467
468
469 //=======================================================================
470 //function : State
471 //purpose  : 
472 //=======================================================================
473
474 TopAbs_State TopOpeBRepBuild_WireEdgeClassifier::State()
475 {
476   TopAbs_State state = myFPC.State();
477   return state;
478 }