0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / TopOpeBRepDS / TopOpeBRepDS_GapFiller.cxx
1 // Created on: 1998-08-19
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1998-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_GapFiller.ixx>
18 #include <TopExp_Explorer.hxx>
19 #include <TopoDS.hxx>
20 #include <TopoDS_Shape.hxx>
21 #include <TopAbs_ShapeEnum.hxx>
22 #include <TopTools_ListIteratorOfListOfShape.hxx>
23 #include <TopOpeBRepDS_ListIteratorOfListOfInterference.hxx>
24 #include <Precision.hxx>
25 #include <TopOpeBRepDS_connex.hxx>
26 #include <TopOpeBRepDS_Point.hxx>
27 #include <TColgp_SequenceOfPnt.hxx>
28 #include <TColStd_MapOfTransient.hxx>
29
30 #include <BRepAdaptor_Curve.hxx>
31 #include <BRepAdaptor_Surface.hxx>
32
33 #include <gp.hxx>
34 #include <gp_Pnt.hxx>
35 #include <gp_Pln.hxx>
36 #include <gp_Dir.hxx>
37 #include <gp_Vec.hxx>
38
39 #include <Geom2d_Curve.hxx>
40
41 #ifdef OCCT_DEBUG
42 extern Standard_Boolean TopOpeBRepDS_GettraceGAP();
43 extern Standard_Boolean TopOpeBRepDS_GetcontextNOGAP();
44 #endif
45
46 //=======================================================================
47 //function : TopOpeBRepDS_GapFiller
48 //purpose  : 
49 //=======================================================================
50
51 TopOpeBRepDS_GapFiller::TopOpeBRepDS_GapFiller(const Handle(TopOpeBRepDS_HDataStructure)& HDS) 
52 :myHDS(HDS)
53 {
54   myGapTool   = new TopOpeBRepDS_GapTool(HDS);
55   myAsso = new TopOpeBRepDS_Association();
56 }
57
58
59 //=======================================================================
60 //function : Perform
61 //purpose  : 
62 //=======================================================================
63
64 void TopOpeBRepDS_GapFiller::Perform() 
65 {
66
67 #ifdef OCCT_DEBUG
68   if (TopOpeBRepDS_GetcontextNOGAP () != 0) return;
69 #endif
70
71   myGapTool->Init(myHDS);
72   TColStd_MapOfInteger View;
73   //------------------------------------------------------------
74   // APPAIRAGE ...
75   //------------------------------------------------------------
76   Standard_Integer NbCurves = myHDS->NbCurves();
77   for (Standard_Integer i = 1; i <= NbCurves; i++) {
78     TopOpeBRepDS_ListOfInterference& LI = myHDS->ChangeDS().ChangeCurveInterferences(i);
79     for (TopOpeBRepDS_ListIteratorOfListOfInterference it(LI); it.More(); it.Next()) {
80       TopOpeBRepDS_ListOfInterference ALI;
81       const Handle(TopOpeBRepDS_Interference)& I = it.Value();
82       if (I->GeometryType() == TopOpeBRepDS_POINT) {
83         if (View.Add(I->Geometry())) {
84           FindAssociatedPoints (I,ALI);
85           myAsso->Associate(I,ALI);
86         }
87       }
88     }
89   }
90   //--------------------------------------------------------
91   // Modification des Geometries
92   //--------------------------------------------------------
93   BuildNewGeometries();
94 }
95
96 //=======================================================================
97 //function : Contains
98 //purpose  : 
99 //=======================================================================
100
101 Standard_Boolean Contains (const TopoDS_Shape& F,const TopoDS_Shape& E)
102 {
103   TopExp_Explorer exp;
104   for (exp.Init(F,E.ShapeType()); exp.More(); exp.Next()){
105 //  for (TopExp_Explorer exp(F,E.ShapeType()); exp.More(); exp.Next()){
106     if (exp.Current().IsSame(E)) return 1;
107   }
108   return 0;
109 }
110
111
112 //=======================================================================
113 //function : FindAssociatedPoints
114 //purpose  : 
115 //=======================================================================
116
117 void TopOpeBRepDS_GapFiller::FindAssociatedPoints(const Handle(TopOpeBRepDS_Interference)& I,
118                                                   TopOpeBRepDS_ListOfInterference&         LI) 
119 {
120   TopOpeBRepDS_ListIteratorOfListOfInterference itSI(myGapTool->SameInterferences(I));
121   for (; itSI.More();itSI.Next()){ 
122     if (myAsso->HasAssociation(itSI.Value())) return;
123   }
124
125 #ifdef OCCT_DEBUG
126   if (TopOpeBRepDS_GettraceGAP() == 1) {
127     cout<<endl;
128     cout<<"-----------------------------------------------------"<<endl;
129     cout<<" Association Point "<<I->Geometry()<<endl;
130   }
131 #endif
132
133   //------------------------------------------------------------------------
134   // PREMIERE PASSE : Recherche de l association parmi les points qui sont:
135   //                  - sur la meme arete
136   //                  - sur l autre face connexe a l arete.
137   //                  - Dans la meme face coupante.
138   //------------------------------------------------------------------------
139   //----------------------------------------------
140   // LI = { ensemble des interference sur l'arete}
141   //----------------------------------------------
142   TopoDS_Shape E ;
143   if (!myGapTool->EdgeSupport(I,E)) {
144     return;
145   }
146   AddPointsOnShape(E,LI);
147   
148   TopoDS_Face F1,F2,F;
149   if (!myGapTool->FacesSupport(I,F1,F2)) {
150     LI.Clear(); return;
151   }
152
153   if (!Contains(F1,E)) {F = F2; F2 = F1; F1 = F;}
154
155   const TopTools_ListOfShape& LF = FDSCNX_EdgeConnexitySameShape(E,myHDS);
156   //------------------------------------------------------------------------
157   // Si le point de I est sur deux faces connexes a E => connexite des sections
158   // => pas d association a faire.
159   //------------------------------------------------------------------------
160 //   for (TopTools_ListIteratorOfListOfShape itLF(LF); itLF.More(); itLF.Next()) {
161    TopTools_ListIteratorOfListOfShape itLF(LF) ;
162    for ( ; itLF.More(); itLF.Next()) {
163     if (!itLF.Value().IsSame(F1)) {
164       if (IsOnFace(I,TopoDS::Face(itLF.Value()))) {
165         LI.Clear(); return;
166       }
167     }
168   }
169
170   //------------------------------------------------------------------------
171   // LI = { ensemble des interference sur l'arete && sur une autre section ds 
172   // la Face connexe par E} 
173   //------------------------------------------------------------------------
174
175   for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
176     if (!itLF.Value().IsSame(F1)) {
177       FilterByFace(TopoDS::Face(itLF.Value()),LI);
178     }
179   }
180   //--------------------------------------------
181   // LI = LI && point dans la meme face Support2
182   //--------------------------------------------
183   if (!LI.IsEmpty()) 
184     FilterByFace (F2, LI);
185
186   //-------------------------------
187   // Controle et Selection metrique 
188   //-------------------------------
189   if (!LI.IsEmpty()) 
190     FilterByIncidentDistance (F2,I,LI);
191
192   if (!LI.IsEmpty()) {
193     LI.Append(I);
194   }
195    
196 #ifdef OCCT_DEBUG
197    if (TopOpeBRepDS_GettraceGAP() != 0) {  
198      TopOpeBRepDS_ListIteratorOfListOfInterference it(LI);
199      for  (it.Initialize(LI); it.More(); it.Next()) {
200        cout<<" "<<it.Value()->Geometry();
201      }
202      cout<<endl;
203    }
204 #endif
205  }
206
207
208 //=======================================================================
209 //function : CheckConnexity
210 //purpose  : 
211 //=======================================================================
212
213 //Standard_Boolean TopOpeBRepDS_GapFiller::CheckConnexity(TopOpeBRepDS_ListOfInterference& LI) 
214 Standard_Boolean TopOpeBRepDS_GapFiller::CheckConnexity(TopOpeBRepDS_ListOfInterference& ) 
215 {
216   return 1;
217 }
218
219 //=======================================================================
220 //function : AddPointsOnFace
221 //purpose  : 
222 //=======================================================================
223
224 void TopOpeBRepDS_GapFiller::AddPointsOnShape (const TopoDS_Shape&               S,
225                                                TopOpeBRepDS_ListOfInterference& LI) 
226 {
227   const TopOpeBRepDS_ListOfInterference& LIOnE = myHDS->DS().ShapeInterferences(S);
228   for (TopOpeBRepDS_ListIteratorOfListOfInterference it(LIOnE); it.More(); it.Next()){
229     LI.Append(it.Value());
230   }
231 }
232
233 //=======================================================================
234 //function : AddPointsOnConnexShape
235 //purpose  : 
236 //=======================================================================
237
238 //void TopOpeBRepDS_GapFiller::AddPointsOnConnexShape(const TopoDS_Shape&         //           F,
239 //                                                  const TopOpeBRepDS_ListOfInterference& LI) 
240 void TopOpeBRepDS_GapFiller::AddPointsOnConnexShape(const TopoDS_Shape&                    ,
241                                                     const TopOpeBRepDS_ListOfInterference& ) 
242 {
243 }
244
245
246 //=======================================================================
247 //function : FilterbyFace
248 //purpose  : 
249 //=======================================================================
250
251 void TopOpeBRepDS_GapFiller::FilterByFace(const TopoDS_Face&               F,
252                                           TopOpeBRepDS_ListOfInterference& LI) 
253 {
254   //------------------------------------------------------------------------
255   // il ne restera dans LI que les interference dont une des representation 
256   // a ete calculee sur F .
257   //------------------------------------------------------------------------
258   TopOpeBRepDS_ListIteratorOfListOfInterference it(LI); 
259   while (it.More()) {
260     if (!IsOnFace(it.Value(),F)) {
261       LI.Remove(it);
262     }
263     else {      
264       it.Next();
265     }
266   }
267 }
268
269 //=======================================================================
270 //function : IsOnFace
271 //purpose  : 
272 //=======================================================================
273
274 Standard_Boolean TopOpeBRepDS_GapFiller::IsOnFace
275 (const Handle(TopOpeBRepDS_Interference)& I,
276  const TopoDS_Face&                       F) const
277 {
278   TopOpeBRepDS_Curve C;
279   if (myGapTool->Curve(I,C)) {
280     TopoDS_Shape S1,S2;
281     C.GetShapes(S1,S2);
282     if (S1.IsSame(F)) return 1;
283     if (S2.IsSame(F)) return 1;
284   }
285   return 0;
286 }
287
288
289 //=======================================================================
290 //function : FilterbyEdge
291 //purpose  : 
292 //=======================================================================
293
294 void TopOpeBRepDS_GapFiller::FilterByEdge(const TopoDS_Edge&               E,
295                                           TopOpeBRepDS_ListOfInterference& LI) 
296 {  
297   // il ne restera dans LI que les interference dont une des representation 
298   // a pour support E
299   TopOpeBRepDS_ListIteratorOfListOfInterference it(LI);
300   while (it.More()) {
301     if (!IsOnEdge(it.Value(),E)) {
302       LI.Remove(it);
303     }
304     else {      
305       it.Next();
306     }
307   }
308 }
309
310 //=======================================================================
311 //function : IsOnEdge
312 //purpose  : 
313 //=======================================================================
314
315 Standard_Boolean TopOpeBRepDS_GapFiller::IsOnEdge
316 (const Handle(TopOpeBRepDS_Interference)& I,
317  const TopoDS_Edge&                       E) const
318 {
319   const TopOpeBRepDS_ListOfInterference& LI = myGapTool->SameInterferences(I);
320   for (TopOpeBRepDS_ListIteratorOfListOfInterference it(LI); it.More(); it.Next()) {
321     const Handle(TopOpeBRepDS_Interference)& IC = it.Value();
322     if (IC->SupportType() == TopOpeBRepDS_EDGE) {
323       const TopoDS_Shape& S1 = myHDS->Shape(IC->Support());
324       if (S1.IsSame(E)) return 1;
325     }
326   }
327   return 0;
328 }
329
330
331
332 //=======================================================================
333 //function : Normale
334 //purpose  : 
335 //=======================================================================
336
337 static Standard_Boolean Normal(const Handle(TopOpeBRepDS_GapTool)&      A,
338                                const Handle(TopOpeBRepDS_HDataStructure)& HDS,
339                                const Handle(TopOpeBRepDS_Interference)&   I,
340                                const TopoDS_Face&                         F,
341                                gp_Dir&                                    D)
342
343
344   TopOpeBRepDS_Kind GK,SK;
345   Standard_Integer  IG,IS;
346   gp_Pnt   PS;
347   gp_Vec   TU,TV,N;
348   gp_Pnt2d P2d;
349   
350   BRepAdaptor_Surface S(F);
351   if (S.GetType() == GeomAbs_Plane) {
352     D = S.Plane().Axis().Direction();
353     return 1;
354   }
355   
356   const TopOpeBRepDS_ListOfInterference& LI = A->SameInterferences(I);
357   for (TopOpeBRepDS_ListIteratorOfListOfInterference it(LI); it.More(); it.Next()) {
358     const Handle(TopOpeBRepDS_Interference)&   IC = it.Value();
359     IC->GKGSKS(GK,IG,SK,IS);
360     if (SK == TopOpeBRepDS_CURVE) {
361       const TopOpeBRepDS_Curve& C = HDS->Curve(IS);
362       Standard_Real P   = Handle(TopOpeBRepDS_CurvePointInterference)::DownCast (IC)->Parameter();
363       
364       TopoDS_Shape S1,S2;
365       C.GetShapes(S1,S2);
366       if (F.IsSame(S1)) {
367         if (C.Curve1().IsNull()) return 0;
368         P2d = C.Curve1()->Value(P);
369       }
370       else {
371         if (C.Curve2().IsNull()) return 0;
372         P2d = C.Curve2()->Value(P);
373       }
374       
375       if (S.UContinuity() >= GeomAbs_C1 && S.VContinuity() >= GeomAbs_C1) {
376         S.D1(P2d.X(),P2d.Y(),PS,TU,TV);
377         N = TU^TV;
378 //      if (N.SquareMagnitude() >= gp::Resolution()); { // !!
379         if (N.SquareMagnitude() >= gp::Resolution()) {
380           D = gp_Dir(N);
381           return 1;
382         }
383       }
384       return 0;
385     }
386   } 
387   return 0;
388 }
389
390 //=======================================================================
391 //function : FilterByIncidentDistance
392 //purpose  : 
393 //=======================================================================
394
395 void TopOpeBRepDS_GapFiller::FilterByIncidentDistance(const TopoDS_Face& F,
396                                                       const Handle(TopOpeBRepDS_Interference)& I,
397                                                       TopOpeBRepDS_ListOfInterference& LI) 
398 {
399   Standard_Real DistMin = Precision::Infinite();  
400   Handle(TopOpeBRepDS_Interference) ISol;
401   
402   const TopOpeBRepDS_Point& PI1 = myHDS->Point(I->Geometry());
403   const gp_Pnt              GPI = PI1.Point();
404  
405   BRepAdaptor_Surface S(F,0);
406
407   Standard_Real TolDef  = 0.94;// cos(20degre);
408   Standard_Real TolDist = 20*PI1.Tolerance();
409   gp_Dir N1,N2;
410   Standard_Boolean Ok1 = Normal(myGapTool,myHDS,I,F,N1);
411   
412   for (TopOpeBRepDS_ListIteratorOfListOfInterference it(LI);it.More(); it.Next()) {
413     
414     const Handle(TopOpeBRepDS_Interference)& CI = it.Value();
415   
416     if (CI->HasSameGeometry(I)) continue;
417
418     Standard_Boolean          Ok2  = Normal(myGapTool,myHDS,CI,F,N2);
419     const TopOpeBRepDS_Point& P    = myHDS->Point((CI->Geometry()));
420     const gp_Pnt              GP   = P.Point();
421     Standard_Real             Dist = GP.Distance(GPI);
422     
423     //---------------------------------------------------------------------------
424     // Test resjection 
425     // Si les points sont plutot ecartes, on regarde si les Normales sur la face
426     // sont proches   
427     //---------------------------------------------------------------------------
428     if (Dist > TolDist) {
429       if (Ok1 && Ok2) {
430         if (N1.Dot(N2) < TolDef) {
431           continue;  // Reject
432         }
433       }
434       continue; // Reject
435     }
436     
437     if (Dist < DistMin) {
438       DistMin = Dist;
439       ISol    = it.Value();
440     }
441   }
442
443   LI.Clear();
444   if (!ISol.IsNull()) {
445     LI.Append(ISol);
446 #ifdef OCCT_DEBUG
447     if (TopOpeBRepDS_GettraceGAP() == 1){
448       cout << " Distance Minimum :"<<DistMin<<endl; 
449     }
450 #endif
451   }
452 }
453
454 //=======================================================================
455 //function : BuildNewPoint
456 //purpose  : 
457 //=======================================================================
458 //unreferenced function, commented    
459 /*
460 #ifdef OCCT_DEBUG
461 static void BuildNewPoint (const TColgp_SequenceOfPnt& LP,
462                            const Standard_Real&    TolMax,
463                            TopOpeBRepDS_Point& Point) 
464 {
465   if (LP.IsEmpty()) return;
466   Standard_Real xp = 0.,yp = 0.,zp = 0.;
467
468   Standard_Integer i,Nb = LP.Length();
469   for (i = 1; i <= Nb; i++) {
470     const gp_Pnt& CP = LP(i);
471     xp+= CP.X();yp+=CP.Y();zp+=CP.Z();
472   }
473   xp/=Nb;yp/=Nb;zp/=Nb;
474   gp_Pnt NP(xp,yp,zp);  
475
476   Standard_Real DistMax = 0;
477   for (i = 1; i <= Nb; i++) {
478     const gp_Pnt& CP = LP(i);
479     DistMax = Max(CP.Distance(NP),DistMax);
480   }
481   Point.ChangePoint() = NP;
482   Point.Tolerance(DistMax+TolMax);
483 }
484 #endif
485 */
486 //=======================================================================
487 //function : ReBuildGeom
488 //purpose  : 
489 //=======================================================================
490
491 void TopOpeBRepDS_GapFiller::ReBuildGeom(const Handle(TopOpeBRepDS_Interference)& I,
492                                          TColStd_MapOfInteger&                    View) 
493 {
494   if (!myAsso->HasAssociation(I)) return;
495
496   TopOpeBRepDS_ListOfInterference& LI = myAsso->Associated(I);
497   TopOpeBRepDS_ListIteratorOfListOfInterference it(LI);
498
499 #ifdef OCCT_DEBUG
500   if (TopOpeBRepDS_GettraceGAP() == 1) {
501     cout <<"Points ";
502     for  (it.Initialize(LI); it.More(); it.Next()) {
503       cout <<" "<<it.Value()->Geometry();
504     }
505     cout <<endl<<" ---->";
506   }
507 #endif
508
509   Standard_Real TolMax = 0,UMin = Precision::Infinite();
510   Standard_Real UMax = -UMin, U;
511   TopoDS_Edge   E,CE ;
512   myGapTool->EdgeSupport(I,E);
513
514   // Construction du nouveau point
515   for  (it.Initialize(LI); it.More(); it.Next()) {
516     TopOpeBRepDS_Point PP = myHDS->Point(it.Value()->Geometry());
517     TolMax = Max(TolMax,PP.Tolerance());
518     if (myGapTool->ParameterOnEdge (it.Value(),E,U)) {
519       UMin = Min(UMin,U);
520       UMax = Max(UMax,U);
521     }
522     myGapTool->EdgeSupport(it.Value(),CE);
523     if (!CE.IsSame(E)) {
524 #ifdef OCCT_DEBUG
525       if (TopOpeBRepDS_GettraceGAP() == 1){
526         cout <<"GapFiller : points pas sur la meme edge -> cas non traite"<<endl;
527       }
528 #endif
529       return;
530     }
531   }
532   U = (UMax+UMin)*0.5;
533   BRepAdaptor_Curve C(E); gp_Pnt GP = C.Value(U);
534   TopOpeBRepDS_Point P(GP,TolMax);
535
536   // Mise a jour.
537   Standard_Integer IP = myHDS->ChangeDS().AddPoint(P);
538 #ifdef OCCT_DEBUG
539  if (TopOpeBRepDS_GettraceGAP() == 1) {
540    cout <<" New Point : "<<IP<<endl;
541  }
542 #endif
543   for (it.Initialize(LI); it.More(); it.Next()) {
544     View.Add(it.Value()->Geometry());
545     myGapTool->SetParameterOnEdge(it.Value(),E,U); 
546     myGapTool->SetPoint(it.Value(),IP);
547   }
548   myGapTool->SetParameterOnEdge(I,E,U);
549   myGapTool->SetPoint(I,IP);
550   View.Add(IP);
551 }
552
553 //=======================================================================
554 //function : BuildNewGeometries
555 //purpose  : 
556 //=======================================================================
557
558 void TopOpeBRepDS_GapFiller::BuildNewGeometries() 
559 {
560   TColStd_MapOfInteger View;
561   Standard_Integer NbCurves = myHDS->NbCurves();
562   Standard_Integer NbPoints = myHDS->NbPoints();
563   for (Standard_Integer i = 1; i <= NbCurves; i++) {
564     TopOpeBRepDS_ListOfInterference& LI = myHDS->ChangeDS().ChangeCurveInterferences(i);
565     for (TopOpeBRepDS_ListIteratorOfListOfInterference it(LI); it.More(); it.Next()) {
566       Handle(TopOpeBRepDS_Interference) I = it.Value();
567       Standard_Integer IP = I->Geometry();
568       if (View.Add(IP) && IP <= NbPoints) ReBuildGeom(I,View);
569     }
570   } 
571 }
572
573