0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / TopOpeBRepBuild / TopOpeBRepBuild_FuseFace.cxx
1 // Created on: 1998-07-28
2 // Created by: LECLERE Florence
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 <TopOpeBRepBuild_FuseFace.hxx>
18
19 #include <TopTools_ListOfShape.hxx>
20 #include <TopTools_ListIteratorOfListOfShape.hxx>
21 #include <TopTools_MapOfShape.hxx>
22
23 #include <TopTools_DataMapOfShapeListOfShape.hxx>
24 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
25 #include <TopTools_DataMapOfShapeInteger.hxx>
26 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
27
28 #include <TopExp_Explorer.hxx>
29
30 #include <TopoDS.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TopoDS_Wire.hxx>
33 #include <TopoDS_Edge.hxx>
34
35 #include <BRepLib_MakeWire.hxx>
36 #include <BRepLib_MakeFace.hxx>
37 #include <BRepLib_MakeEdge.hxx>
38
39 #include <BRep_Builder.hxx>
40 #include <BRep_Tool.hxx>
41 #include <BRepCheck_Analyzer.hxx>
42
43 #include <Geom_Surface.hxx>
44 #include <Geom_RectangularTrimmedSurface.hxx>
45 #include <Geom_Curve.hxx>
46 #include <Geom_TrimmedCurve.hxx>
47 #include <Geom_Line.hxx>
48 #include <Geom_Circle.hxx>
49 #include <Geom_Ellipse.hxx>
50 #include <Geom_BSplineCurve.hxx>
51 #include <Geom_BezierCurve.hxx>
52 #include <TColgp_Array1OfPnt.hxx>
53 #include <TColStd_Array1OfReal.hxx>
54 #include <TColStd_Array1OfInteger.hxx>
55 #include <ElCLib.hxx>
56 #include <Precision.hxx>
57
58 #ifdef OCCT_DEBUG
59 extern Standard_Boolean TopOpeBRepBuild_GettraceFUFA();
60 #endif
61
62 static void GroupShape(TopTools_ListOfShape&,
63                        Standard_Boolean,
64                        TopTools_DataMapOfShapeListOfShape&);
65
66 static void GroupEdge(TopTools_DataMapOfShapeListOfShape&,
67                       TopTools_DataMapOfShapeListOfShape&);
68
69 static void MakeEdge(TopTools_DataMapOfShapeListOfShape&);
70
71 static Standard_Boolean SameSupport(const TopoDS_Edge&,
72                                     const TopoDS_Edge&);
73
74 //=======================================================================
75 //function : Init
76 //purpose  : 
77 //=======================================================================
78 void TopOpeBRepBuild_FuseFace::Init(const TopTools_ListOfShape& LIF,
79                                     const TopTools_ListOfShape& LRF,
80                                     const Standard_Integer CXM)
81 {
82 #ifdef OCCT_DEBUG
83   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
84   if (trc) cout << "TopOpeBRepBuild_FuseFace::Init" << endl;
85 #endif
86   myLIF = LIF;
87   myLRF = LRF;
88   if(CXM == 1) {
89     myInternal = Standard_False;
90   }
91   else if(CXM == 2) {
92     myInternal = Standard_True;
93   } // CXM
94 #ifdef OCCT_DEBUG
95   if (trc) {
96     if (myInternal) {
97       cout << " TopOpeBRepBuild_FuseFace::Init : Keep internal connections" << endl;
98     } else {
99       cout << " TopOpeBRepBuild_FuseFace::Init : Suppress internal connections" << endl;
100     }
101   }
102 #endif
103
104   myLFF.Clear();
105
106   myLIE.Clear();
107   myLEE.Clear();
108   myLME.Clear();
109
110   myLIV.Clear();
111   myLEV.Clear();
112   myLMV.Clear();
113
114   myModified = Standard_False;
115   myDone = Standard_False;
116
117 }
118
119 //=======================================================================
120 //function : PerformFace
121 //purpose  : fusion des faces cosurfaciques, connexes par une ou 
122 //plusieurs aretes       
123 //=======================================================================
124
125 void TopOpeBRepBuild_FuseFace::PerformFace()
126 {
127 #ifdef OCCT_DEBUG
128   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
129   if (trc) cout << "TopOpeBRepBuild_FuseFace::PerformFace()" << endl;
130 #endif
131
132   myModified = Standard_False;
133   myLFF.Clear();
134   if (myLRF.IsEmpty()) {
135 #ifdef OCCT_DEBUG
136     if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Empty list of reconstructed faces"<<endl;
137 #endif
138     myModified = Standard_False;
139     myDone = Standard_True;
140     myLFF = myLRF;
141     return;
142   }
143
144   Standard_Integer number = myLRF.Extent();
145   if (number == 1) {
146 #ifdef OCCT_DEBUG
147     if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : only 1 reconstructed face"<<endl;
148 #endif
149     myModified = Standard_False;
150     myDone = Standard_True;
151     myLFF = myLRF;
152     return;
153   }
154     
155   TopTools_ListIteratorOfListOfShape it2,it3,it4;
156   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itt1,itt2,itt3;
157   TopAbs_Orientation ori1;
158
159   Standard_Boolean Ori3dReversed = Standard_False;
160   Standard_Boolean Ori3dForward = Standard_False;
161   TopTools_ListOfShape mylist;
162   for(it2.Initialize(myLRF); it2.More(); it2.Next()) {
163     TopoDS_Shape fac = it2.Value();
164     ori1 = fac.Orientation();
165     if (ori1 == TopAbs_FORWARD) {
166       Ori3dForward = Standard_True;
167     }
168     if (ori1 == TopAbs_REVERSED) {
169       Ori3dReversed = Standard_True;
170     }
171     BRepCheck_Analyzer ana(fac);
172     if (!ana.IsValid(fac)) {
173 //    if (!BRepCheck_Analyzer::IsValid(fac)) {
174 #ifdef OCCT_DEBUG
175       if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Invalid reconstructed face"<<endl;
176 #endif
177       myModified = Standard_False;
178       myDone = Standard_True;
179       myLFF = myLRF;
180       return;
181     }
182     fac.Orientation(TopAbs_FORWARD);
183     mylist.Append(fac);
184   }
185
186 // Orientation 3d de l'espace limite par la face
187   if (Ori3dForward && Ori3dReversed) {
188 #ifdef OCCT_DEBUG
189     if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Bad faces 3d orientation"<<endl;
190 #endif
191     myModified = Standard_False;
192     myDone = Standard_True;
193     myLFF = myLRF;
194     return;
195   }
196   
197 // listes de faces avec edges communes.
198   Standard_Boolean Keep_Edge;
199   Keep_Edge = Standard_False;
200   TopTools_DataMapOfShapeListOfShape mapFacLFac;
201   GroupShape(mylist,Keep_Edge,mapFacLFac);
202   if (mapFacLFac.IsEmpty()) {
203 #ifdef OCCT_DEBUG
204     if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Empty list of faces"<<endl;
205 #endif
206     myModified = Standard_False;
207     myDone = Standard_True;
208     myLFF = myLRF;
209     return;
210   }
211   Standard_Integer n1 = myLRF.Extent();
212   Standard_Integer n2 = mapFacLFac.Extent();
213   if (n1 == n2) {
214 #ifdef OCCT_DEBUG
215     if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : No connection"<<endl;
216 #endif
217     myModified = Standard_False;
218     myDone = Standard_True;
219     myLFF = myLRF;
220     return;
221   }
222
223   
224 //boucle sur les listes des faces de 1 face de LRF
225     
226   for (itt1.Initialize(mapFacLFac); itt1.More(); itt1.Next()) {
227     const TopoDS_Shape& fac = itt1.Key();
228     TopoDS_Face facref = TopoDS::Face(fac);
229     const TopTools_ListOfShape& LFac = mapFacLFac.Find(fac);
230     
231     Standard_Integer n11 = LFac.Extent();
232     if (n11 != 1) {
233       TopTools_ListOfShape LWir;
234       for(it2.Initialize(LFac); it2.More(); it2.Next()) {
235         const TopoDS_Shape& fac1 = it2.Value();
236         
237         TopExp_Explorer exp;
238         for (exp.Init(fac1,TopAbs_WIRE); exp.More(); exp.Next()) {
239           const TopoDS_Shape& wir = exp.Current();
240           LWir.Append(wir);
241         }
242       } // LFac
243       //  listes des wires avec edges communes.
244       Keep_Edge = Standard_False;
245       TopTools_DataMapOfShapeListOfShape mapWirLWir;
246       GroupShape(LWir,Keep_Edge,mapWirLWir);
247       if (mapWirLWir.IsEmpty()) {
248 #ifdef OCCT_DEBUG
249         if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Empty list of wires"<<endl;
250 #endif
251         myModified = Standard_False;
252         myDone = Standard_True;
253         myLFF = myLRF;
254         return;
255       } 
256       
257 //  boucle sur les listes des wires de 1 face de LRF
258       TopTools_ListOfShape myFaceLIE,myFaceLEE,myFaceLME,myFaceLW;
259       for (itt2.Initialize(mapWirLWir); itt2.More(); itt2.Next()) {
260         const TopoDS_Shape& wir = itt2.Key();
261         const TopTools_ListOfShape& LWir1 = mapWirLWir.Find(wir);
262         
263         Standard_Integer n22 = LWir1.Extent();
264         if (n22 != 1) { 
265 //    boucle sur 1 liste des wires avec edges communes.
266           TopTools_ListOfShape LEdg;
267           for(it3.Initialize(LWir1); it3.More(); it3.Next()) {
268             const TopoDS_Shape& wir1 = it3.Value();
269             
270             TopExp_Explorer exp;
271             for (exp.Init(wir1,TopAbs_EDGE); exp.More(); exp.Next()) {
272               const TopoDS_Shape& edg = exp.Current();
273               LEdg.Append(edg);
274             }
275           } // LWir1
276 //    listes des edges avec edges communes.
277           Keep_Edge = Standard_True;
278           TopTools_DataMapOfShapeListOfShape mapEdgLEdg;
279           GroupShape(LEdg,Keep_Edge,mapEdgLEdg);
280           if (mapEdgLEdg.IsEmpty()) {
281 #ifdef OCCT_DEBUG
282             if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Empty list of edges"<<endl;
283 #endif
284             myModified = Standard_False;
285             myDone = Standard_True;
286             myLFF = myLRF;
287             return;
288           } 
289         
290 //    Elimination selon logique pure
291 //    boucle sur les listes des egdes de 1 wire de 1 face de LRF
292           TopTools_ListOfShape myWireLE;
293           for (itt3.Initialize(mapEdgLEdg); itt3.More(); itt3.Next()) {
294             const TopoDS_Shape& edg = itt3.Key();
295             const TopTools_ListOfShape& LEdg1 = mapEdgLEdg.Find(edg);
296             Standard_Boolean OriReversed = Standard_False;
297             Standard_Boolean OriForward = Standard_False;
298             Standard_Boolean OriInternal = Standard_False;
299             Standard_Boolean OriExternal = Standard_False;
300             for(it4.Initialize(LEdg1); it4.More(); it4.Next()) {
301               const TopoDS_Shape& edg1 = it4.Value();
302               ori1 = edg1.Orientation();
303               if (ori1 == TopAbs_REVERSED) {
304                 if (OriReversed) {
305 #ifdef OCCT_DEBUG
306                   if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Bad faces orientation"<<endl;
307 #endif
308                   myModified = Standard_False;
309                   myDone = Standard_True;
310                   myLFF = myLRF;
311                   return;
312                 }
313                 OriReversed = Standard_True;
314               }
315               else if (ori1 == TopAbs_FORWARD) {
316                 if (OriForward) {
317 #ifdef OCCT_DEBUG
318                   if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Bad faces orientation"<<endl;
319 #endif
320                   myModified = Standard_False;
321                   myDone = Standard_True;
322                   myLFF = myLRF;
323                   return;
324                 }
325                 OriForward = Standard_True;
326               }
327               else if (ori1 == TopAbs_INTERNAL) {
328                 OriInternal = Standard_True;
329               }
330               else if (ori1 == TopAbs_EXTERNAL) {
331                 OriExternal = Standard_True;
332               }
333             } // LEdg1
334           
335 //      - Traitement edge selon orientation
336 //      On privilegie orientation selon 1) reversed ou forward
337 //                                      2) internal
338 //                                      3) external
339 //      pour traiter cas ou l'on a au moins 2 orientations differentes parmi
340 //           forward et reversed - interne - externe 
341         
342             if (OriReversed || OriForward) {
343               if (OriReversed && OriForward) {
344 //              TopoDS_Shape& edg1 = edg.Oriented(TopAbs_INTERNAL);
345                 const TopoDS_Shape& edg1 = edg.Oriented(TopAbs_INTERNAL);
346                 myLME.Append(edg1);
347                 myFaceLME.Append(edg1);
348               } else if (OriReversed) {
349 //              TopoDS_Shape& edg1 = edg.Oriented(TopAbs_REVERSED);
350                 const TopoDS_Shape& edg1 = edg.Oriented(TopAbs_REVERSED);
351                 myWireLE.Append(edg1);
352               } else {
353 //              TopoDS_Shape& edg1 = edg.Oriented(TopAbs_FORWARD);
354                 const TopoDS_Shape& edg1 = edg.Oriented(TopAbs_FORWARD);
355                 myWireLE.Append(edg1);
356               }
357             } 
358             else if (OriInternal) {
359 //            TopoDS_Shape& edg1 = edg.Oriented(TopAbs_INTERNAL);
360               const TopoDS_Shape& edg1 = edg.Oriented(TopAbs_INTERNAL);
361               myLIE.Append(edg1);
362               myFaceLIE.Append(edg1);
363             }
364             else if (OriExternal) {
365 //            TopoDS_Shape& edg1 = edg.Oriented(TopAbs_EXTERNAL);
366               const TopoDS_Shape& edg1 = edg.Oriented(TopAbs_EXTERNAL);
367               myLEE.Append(edg1);
368               myFaceLEE.Append(edg1);
369             } // Ori
370           } // mapEdgLEdg
371         
372 //    Reconstrution de 1 wire de 1 face de LRF
373 //    Attention cas ou une liste de wire connectes conduit a plusieurs Wires
374           Standard_Integer number1 = myWireLE.Extent();
375           while (number1 > 0) {
376             BRepLib_MakeWire MW;
377             MW.Add(myWireLE);
378             if (!MW.IsDone()) {
379 #ifdef OCCT_DEBUG
380               if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Failure in making wire"<<endl;
381 #endif
382               myModified = Standard_False;
383               myDone = Standard_True;
384               myLFF = myLRF;
385               return;
386             }
387             
388 //    Astuce pour contourner Wire Not Closed
389             TopoDS_Wire W = MW.Wire();
390             BRepLib_MakeWire MW1(W);
391             W = MW1.Wire();
392             
393             myFaceLW.Append(W);   
394             
395             TopExp_Explorer exp;
396             TopTools_MapOfShape M;
397             Standard_Integer nb = 0;
398             for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
399               const TopoDS_Shape& edg3 = exp.Current();
400               M.Add(edg3);
401               nb++;
402             }
403             
404             if (nb == number1) {
405               number1 = 0 ;
406             }
407             else {
408               TopTools_ListOfShape ListEdge;
409               for(it3.Initialize(myWireLE); it3.More(); it3.Next()) {
410                 const TopoDS_Shape& edg2 = it3.Value();
411                 if (M.Add(edg2)) {
412                   ListEdge.Append(edg2);
413                 }
414               }
415               myWireLE.Assign(ListEdge);
416               number1 = myWireLE.Extent();
417             } // nb
418           } // number
419         }
420         else {
421           myFaceLW.Append(wir);
422         } // n2 =1
423       } // mapWirLWir
424       
425 //  Reconstrution de 1 face de LRF
426       Handle(Geom_Surface) S = BRep_Tool::Surface(facref);
427       if (S->DynamicType() == 
428           STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
429         S = Handle(Geom_RectangularTrimmedSurface)::
430           DownCast(S)->BasisSurface();
431       }
432       BRepLib_MakeFace MF(S, Precision::Confusion());  
433
434       for(it2.Initialize(myFaceLW); it2.More(); it2.Next()) {
435         const TopoDS_Wire& wir1 = TopoDS::Wire(it2.Value());
436         MF.Add(wir1);
437       }
438
439 // Ajout des Edges Internes
440 //                 Externes
441 //                 Modifiees
442       for (it2.Initialize(myFaceLIE); it2.More(); it2.Next()) {
443         const TopoDS_Edge& edg1 = TopoDS::Edge(it2.Value());
444         BRepLib_MakeWire MW(edg1);
445 //      MW.Add(edg1);
446         const TopoDS_Wire& W = MW.Wire();
447         MF.Add(W);
448       }
449       for (it2.Initialize(myFaceLEE); it2.More(); it2.Next()) {
450         const TopoDS_Edge& edg1 = TopoDS::Edge(it2.Value());
451         BRepLib_MakeWire MW(edg1);
452 //      MW.Add(edg1);
453         const TopoDS_Wire& W = MW.Wire();
454         MF.Add(W);
455       }
456       if (myInternal) {
457         for (it2.Initialize(myFaceLME); it2.More(); it2.Next()) {
458           const TopoDS_Edge& edg1 = TopoDS::Edge(it2.Value());
459           BRepLib_MakeWire MW(edg1);
460 //        MW.Add(edg1);
461           const TopoDS_Wire& W = MW.Wire();
462           MF.Add(W);
463         }
464       }
465
466       if (!MF.IsDone()) {
467 #ifdef OCCT_DEBUG
468         if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Failure in making face"<<endl;
469 #endif
470         myModified = Standard_False;
471         myDone = Standard_True;
472         myLFF = myLRF;
473         return;
474       }
475       TopoDS_Face F = MF.Face();
476       if (Ori3dReversed) {
477         F.Reverse();
478       }
479       myLFF.Append(F);
480     }
481     else {
482       myLFF.Append(facref);
483     } // n1 = 1
484   } // mapFacLFac
485  
486   if (myLFF.IsEmpty()) {
487 #ifdef OCCT_DEBUG
488     if (trc) cout<<" TopOpeBRepBuild_FuseFace::PerformFace : Empty list of fusionned faces"<<endl;
489 #endif
490     myModified = Standard_False;
491     myDone = Standard_True;
492     myLFF = myLRF;
493     return;
494   }
495   
496   myModified = Standard_True;
497   myDone = Standard_True;
498
499 #ifdef OCCT_DEBUG
500   if (trc) cout << " TopOpeBRepBuild_FuseFace::PerformFace() : Done" << endl;
501 #endif
502 }
503
504 //=======================================================================
505 //function : PerformEdge
506 //purpose  : fusion des edges cosurfaciques, connexes par une ou 
507 //plusieurs aretes       
508 //=======================================================================
509
510 void TopOpeBRepBuild_FuseFace::PerformEdge()
511 {
512 #ifdef OCCT_DEBUG
513   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
514   if (trc) cout << "TopOpeBRepBuild_FuseFace::PerformEdge()" << endl;
515 #endif
516   TopTools_DataMapOfShapeListOfShape mapVerLEdg,mapTampon;
517
518   TopTools_ListIteratorOfListOfShape it1;
519   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itt1;
520 //  TopAbs_Orientation ori,ori1;
521   
522 //Niveau 1
523 //boucle sur les listes des faces de 1 face de LRF
524     
525   for (it1.Initialize(myLFF); it1.More(); it1.Next()) {
526     const TopoDS_Shape& fac = it1.Value();
527       
528     TopExp_Explorer expw;
529     for (expw.Init(fac,TopAbs_WIRE); expw.More(); expw.Next()) {
530       const TopoDS_Shape& wir = expw.Current();
531    
532       TopExp_Explorer expe;
533       for (expe.Init(wir,TopAbs_EDGE); expe.More(); expe.Next()) {
534         const TopoDS_Shape& edg = expe.Current();
535       
536         TopExp_Explorer expv;
537         for (expv.Init(edg,TopAbs_VERTEX); expv.More(); expv.Next()) {
538           const TopoDS_Shape& ver = expv.Current();
539           if (!mapVerLEdg.IsBound(ver)) {
540             TopTools_ListOfShape LmapEdg;
541             LmapEdg.Append(edg);
542             mapVerLEdg.Bind(ver,LmapEdg);
543           }
544           else {
545             TopTools_ListOfShape& LmapEdg = mapVerLEdg.ChangeFind(ver);
546             LmapEdg.Append(edg);
547           }
548         }
549       }
550     }
551   }
552
553 //nettoyage du tableau mapVerLSh : shap1 : shap1 shap2 shap3
554 //On ne garde que les vertex qui appartiennent a - exactement 2 edges
555 //                                               - de meme support geometrique
556   mapTampon = mapVerLEdg;
557   mapVerLEdg.Clear();
558  
559   for (itt1.Initialize(mapTampon); itt1.More(); itt1.Next()) {
560     const TopoDS_Shape& ver = itt1.Key();
561     const TopTools_ListOfShape& LmapEdg = mapTampon.Find(ver);
562     Standard_Integer number = LmapEdg.Extent();
563     if (number == 2){
564       it1.Initialize(LmapEdg);
565       const TopoDS_Edge& edg1 = TopoDS::Edge(it1.Value());  
566       it1.Next();
567       const TopoDS_Edge& edg2 = TopoDS::Edge(it1.Value());      
568       if (SameSupport(edg1,edg2)) {
569         mapVerLEdg.Bind(ver,LmapEdg);
570       }
571     }
572   }
573
574 //On regroupe ensemble tous les edges consecutifs et SameSupport
575   TopTools_DataMapOfShapeListOfShape mapEdgLEdg;
576   GroupEdge(mapVerLEdg,mapEdgLEdg);
577
578 //On construit les edges somme des edges consecutifs et SameSupport
579   MakeEdge(mapEdgLEdg);
580
581   myModified = Standard_True;
582   myDone = Standard_True;
583
584 #ifdef OCCT_DEBUG
585   if (trc) cout << " TopOpeBRepBuild_FuseFace::PerformEdge() : Done" << endl;
586 #endif
587 }
588
589 //=======================================================================
590 //function : ClearEdge
591 //purpose  : Nettoyage des Faces : Suppression des edges internes et externes     
592 //=======================================================================
593
594 void TopOpeBRepBuild_FuseFace::ClearEdge()
595 {
596 #ifdef OCCT_DEBUG
597   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
598   if (trc) cout << "TopOpeBRepBuild_FuseFace::ClearEdge()" << endl;
599 #endif
600
601   TopTools_ListIteratorOfListOfShape it1,it2;
602   TopAbs_Orientation ori;
603   TopTools_ListOfShape myLFFnew;
604   
605 //Niveau 1
606 //boucle sur les listes des faces de 1 face de LRF
607     
608   for (it1.Initialize(myLFF); it1.More(); it1.Next()) {
609     const TopoDS_Shape& fac = it1.Value();
610
611     TopTools_ListOfShape myFaceLW;
612     TopExp_Explorer expw;
613     for (expw.Init(fac,TopAbs_WIRE); expw.More(); expw.Next()) {
614       const TopoDS_Shape& wir = expw.Current();
615
616       TopTools_ListOfShape myWireLE;    
617       TopExp_Explorer expe;
618       for (expe.Init(wir,TopAbs_EDGE); expe.More(); expe.Next()) {
619         const TopoDS_Shape& edg = expe.Current();
620         
621 //    Elimination selon des edges interne et externe
622
623         ori = edg.Orientation();
624         if (ori == TopAbs_INTERNAL) {
625           myLIE.Append(edg);
626         }
627         else if (ori == TopAbs_EXTERNAL) {
628           myLEE.Append(edg);
629         }
630         else {
631           myWireLE.Append(edg);
632         }
633       }
634 //    Fin Niveau 3 
635 //    Reconstrution de 1 wire de 1 face de LRF
636       if (!myWireLE.IsEmpty()) {
637         BRepLib_MakeWire MW;
638         MW.Add(myWireLE);
639         if (!MW.IsDone()) {
640 #ifdef OCCT_DEBUG
641           if (trc) cout<<" TopOpeBRepBuild_FuseFace::ClearEdge : Failure in making wire"<<endl;
642 #endif
643           myModified = Standard_False;
644           myDone = Standard_True;
645           myLFF = myLRF;
646           return;
647         }
648         
649         //    Astuce pour contourner Wire Not Closed
650         TopoDS_Wire W = MW.Wire();
651         BRepLib_MakeWire MW1(W);
652         W = MW1.Wire();
653         
654         myFaceLW.Append(W);
655       }
656     }
657 //  Fin Niveau 2
658 //  Reconstrution de 1 face de LRF
659     if (myFaceLW.IsEmpty()) {
660 #ifdef OCCT_DEBUG
661       if (trc) cout<<" TopOpeBRepBuild_FuseFace::ClearEdge : Empty list of wires"<<endl;
662 #endif
663       myModified = Standard_False;
664       myDone = Standard_True;
665       myLFF = myLRF;
666       return;
667     }
668     it2.Initialize(myFaceLW);
669     const TopoDS_Wire& wir = TopoDS::Wire(it2.Value());
670     const Standard_Boolean OnlyPlane = Standard_False;
671     BRepLib_MakeFace MF(wir,OnlyPlane);
672
673     it2.Next();    
674     for( ; it2.More(); it2.Next()) {
675       const TopoDS_Wire& wir1 = TopoDS::Wire(it2.Value());
676       MF.Add(wir1);
677     }
678     if (!MF.IsDone()) {
679 #ifdef OCCT_DEBUG
680       if (trc) cout<<" TopOpeBRepBuild_FuseFace::ClearEdge : Failure in making face"<<endl;
681 #endif
682       myModified = Standard_False;
683       myDone = Standard_True;
684       myLFF = myLRF;
685       return;
686     }
687     const TopoDS_Face& F = MF.Face();
688     myLFFnew.Append(F);
689   }
690 //Fin Niveau 1 
691   if (myLFFnew.IsEmpty()) {
692 #ifdef OCCT_DEBUG
693     if (trc) cout<<" TopOpeBRepBuild_FuseFace::ClearEdge : Empty list of fusionned faces"<<endl;
694 #endif
695     myModified = Standard_False;
696     myDone = Standard_True;
697     myLFF = myLRF;
698     return;
699   }
700   myLFF = myLFFnew;
701
702   myModified = Standard_True;
703   myDone = Standard_True;
704
705 #ifdef OCCT_DEBUG
706   if (trc) cout << " TopOpeBRepBuild_FuseFace::ClearEdge() : Done" << endl;
707 #endif
708 }
709
710 //=======================================================================
711 //function : ClearVertex
712 //purpose  : Nettoyage des Faces : Suppression des vertex internes et externes     
713 //=======================================================================
714
715 void TopOpeBRepBuild_FuseFace::ClearVertex()
716 {
717 #ifdef OCCT_DEBUG
718   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
719   if (trc) cout << "TopOpeBRepBuild_FuseFace::ClearVertex()" << endl;
720 #endif
721
722 #ifdef OCCT_DEBUG
723   if (trc) cout << " TopOpeBRepBuild_FuseFace::ClearVertex() : Done" << endl;
724 #endif
725 }
726
727 //=======================================================================
728 //function : GroupShape
729 //purpose  : 
730 //=======================================================================
731
732 static void GroupShape(TopTools_ListOfShape& mylist,Standard_Boolean Keep_Edge, TopTools_DataMapOfShapeListOfShape& mymapShLSh)
733 {
734   TopTools_ListIteratorOfListOfShape it,it1,it2;
735   TopTools_DataMapOfShapeListOfShape mapEdgLSh,mapShLSh;
736   TopTools_ListOfShape LmapSh4;
737   TopAbs_Orientation ori;
738
739 // construction du tableau C=locmapEdgLSh : egde1 - shap1 shap2 shap3
740 // construction du tableau   locmapShLSh  : shap1 - shap1 shap2 shap3
741   LmapSh4.Clear();
742   for(it.Initialize(mylist); it.More(); it.Next()) {
743     const TopoDS_Shape& shap1 = it.Value();
744     TopTools_ListOfShape LmapSh;
745     LmapSh.Append(shap1);
746
747     mapShLSh.Bind(shap1,LmapSh);
748     
749     TopExp_Explorer expe;
750     for (expe.Init(shap1,TopAbs_EDGE); expe.More(); expe.Next()) {
751       const TopoDS_Shape& edg1 = expe.Current();
752 //    verification si Edge a prendre en compte
753       ori = edg1.Orientation();
754       Standard_Boolean Edge_OK = Standard_True;
755       if (ori == TopAbs_INTERNAL || ori == TopAbs_EXTERNAL) {
756         Edge_OK = Standard_False;
757       }
758       if (Edge_OK || Keep_Edge) {
759         if (!mapEdgLSh.IsBound(edg1)) {
760           TopTools_ListOfShape LmapEdg;
761           LmapEdg.Append(shap1);
762           mapEdgLSh.Bind(edg1,LmapEdg);
763         }
764         else {
765           TopTools_ListOfShape& LmapEdg = mapEdgLSh.ChangeFind(edg1);
766           LmapEdg.Append(shap1);
767           
768           if (!Keep_Edge) {
769             
770 //          Recuperation premier shape de liste liee a edg1
771             it1.Initialize(LmapEdg);
772             const TopoDS_Shape& shap2 = it1.Value();
773             
774 //          Controle si premier shape et shape courant sont deja lies
775             TopTools_ListOfShape LmapSh1;
776             LmapSh1 = mapShLSh.Find(shap2);
777             for(it1.Initialize(LmapSh1); it1.More(); it1.Next()) {
778               const TopoDS_Shape& shap = it1.Value();
779               if (shap.IsSame(shap1)) {
780                 break;
781               }
782             }
783 //          Premier shape et Shape courant ne sont pas deja lies
784             if (!it1.More()){
785               const TopTools_ListOfShape& LmapSh11 = mapShLSh.Find(shap1);
786               const TopTools_ListOfShape& LmapSh2 = mapShLSh.Find(shap2);
787               TopTools_ListOfShape Lmap1;
788               TopTools_ListOfShape Lmap2;
789               Lmap1.Assign(LmapSh11);
790               Lmap2.Assign(LmapSh2);
791              
792               for(it2.Initialize(Lmap1); it2.More(); it2.Next()) {
793                 const TopoDS_Shape& shap = it2.Value();
794                 TopTools_ListOfShape& Lmap = mapShLSh.ChangeFind(shap);
795                 TopTools_ListOfShape Lmap3;
796                 Lmap3.Assign(Lmap2);
797                 Lmap.Append(Lmap3);
798               }
799               for(it2.Initialize(Lmap2); it2.More(); it2.Next()) {
800                 const TopoDS_Shape& shap = it2.Value();
801                 TopTools_ListOfShape& Lmap = mapShLSh.ChangeFind(shap);
802                 TopTools_ListOfShape Lmap3;
803                 Lmap3.Assign(Lmap1);
804                 Lmap.Append(Lmap3);
805               }
806             }
807           }
808         }
809       }
810     }
811   }
812   
813 // nettoyage du tableau mapShLSh : shap1 : shap1 shap2 shap3
814   mymapShLSh.Clear();
815
816   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itt;
817   if (!Keep_Edge) {
818     TopTools_MapOfShape M;
819     for (itt.Initialize(mapShLSh); itt.More(); itt.Next()) {
820       const TopoDS_Shape& shap1 = itt.Key();
821       if (M.Add(shap1)) {
822         const TopTools_ListOfShape& LmapSh = mapShLSh.Find(shap1);
823         mymapShLSh.Bind(shap1,LmapSh);
824         
825         for(it1.Initialize(LmapSh); it1.More(); it1.Next()) {
826           const TopoDS_Shape& shap2 = it1.Value();
827           M.Add(shap2);
828         }
829       }
830     }
831   }
832   else {
833      mymapShLSh = mapEdgLSh;
834   }
835 }
836
837 //=======================================================================
838 //function : GroupEdge
839 //purpose  : 
840 //=======================================================================
841
842 static void GroupEdge(TopTools_DataMapOfShapeListOfShape& mymapVerLEdg, TopTools_DataMapOfShapeListOfShape& mymapEdgLEdg)
843 {
844   TopTools_ListIteratorOfListOfShape it1,it2;
845   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itt;
846   TopTools_DataMapOfShapeListOfShape mapEdgLEdg;
847
848 // construction du tableau C=locmapEdgLSh : egde1 - shap1 shap2 shap3
849 // construction du tableau   locmapShLSh  : shap1 - shap1 shap2 shap3
850   for(itt.Initialize(mymapVerLEdg); itt.More(); itt.Next()) {
851     const TopoDS_Shape& ver1 = itt.Key();
852     TopTools_ListOfShape LmapEdg;
853     LmapEdg = mymapVerLEdg.Find(ver1);
854
855     it1.Initialize(LmapEdg);
856     const TopoDS_Edge& edg1 = TopoDS::Edge(it1.Value());  
857     it1.Next();
858     const TopoDS_Edge& edg2 = TopoDS::Edge(it1.Value());
859
860     Standard_Boolean Edge1Add,Edge2Add;
861     TopoDS_Edge edgold,edgnew;
862     if (mapEdgLEdg.IsBound(edg1)) {
863       Edge1Add = Standard_False;
864       edgold = edg1;
865     } else {
866       Edge1Add = Standard_True;
867       edgnew = edg1;
868     }
869     if (mapEdgLEdg.IsBound(edg2)) {
870       Edge2Add = Standard_False;
871       edgold = edg2;
872     } else {
873       Edge2Add = Standard_True;
874       edgnew = edg2;
875     }
876
877     if (!(Edge1Add || Edge2Add)) {
878       continue;
879     }
880     else if (Edge1Add && Edge2Add) {
881       mapEdgLEdg.Bind(edg1,LmapEdg);
882       mapEdgLEdg.Bind(edg2,LmapEdg);
883     }
884     else {
885  
886
887 //    Recuperation premier shape de liste liee a edg1 et mise a jour  
888
889       TopTools_ListOfShape LmapEdg11;
890       LmapEdg11.Append(edgnew);
891       mapEdgLEdg.Bind(edgnew,LmapEdg11);
892
893       TopTools_ListOfShape LmapEdg1;
894       LmapEdg1 = mapEdgLEdg.Find(edgold);
895    
896       for(it2.Initialize(LmapEdg1); it2.More(); it2.Next()) {
897         const TopoDS_Shape& edg22 = it2.Value();
898         TopTools_ListOfShape& LmapEdg2 = mapEdgLEdg.ChangeFind(edgnew);
899         LmapEdg2.Append(edg22);
900         TopTools_ListOfShape& LmapEdg3 = mapEdgLEdg.ChangeFind(edg22);
901         LmapEdg3.Append(edgnew);
902       }
903     }
904   }
905
906 // nettoyage du tableau mapEdgLedg : edg1 : edg1 edg2 edg3
907   
908   TopTools_MapOfShape M;
909
910   for (itt.Initialize(mapEdgLEdg); itt.More(); itt.Next()) {
911     const TopoDS_Shape& edg1 = itt.Key();
912     if (M.Add(edg1)) {
913       const TopTools_ListOfShape& LmapEdg = mapEdgLEdg.Find(edg1);
914       mymapEdgLEdg.Bind(edg1,LmapEdg);
915       
916       for(it1.Initialize(LmapEdg); it1.More(); it1.Next()) {
917         const TopoDS_Shape& edg2 = it1.Value();
918         M.Add(edg2);
919       }
920     }
921   }
922 }
923
924 //=======================================================================
925 //function : MakeEdge
926 //purpose  : 
927 //=======================================================================
928
929 static void MakeEdge(TopTools_DataMapOfShapeListOfShape& mymapEdgLEdg)
930 {
931 #ifdef OCCT_DEBUG
932   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
933 #endif
934
935   TopTools_ListIteratorOfListOfShape it;
936   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itt1;
937   TopTools_DataMapIteratorOfDataMapOfShapeInteger itt2;
938   TopTools_DataMapOfShapeListOfShape mapEdgLEdg;
939
940 // construction du tableau C=locmapEdgLSh : egde1 - shap1 shap2 shap3
941 // construction du tableau   locmapShLSh  : shap1 - shap1 shap2 shap3
942   for(itt1.Initialize(mymapEdgLEdg); itt1.More(); itt1.Next()) {
943     const TopoDS_Shape& edg1 = itt1.Key();
944     TopTools_ListOfShape LmapEdg;
945     LmapEdg = mymapEdgLEdg.Find(edg1);
946     TopTools_DataMapOfShapeInteger mapVerInt;
947
948     Standard_Integer VertexExtrem;
949     TopoDS_Vertex V1,V2;
950     for(it.Initialize(LmapEdg); it.More(); it.Next()) {
951       const TopoDS_Edge& edg2 = TopoDS::Edge(it.Value());
952
953       TopExp_Explorer expv;
954       for (expv.Init(edg2,TopAbs_VERTEX); expv.More(); expv.Next()) {
955         const TopoDS_Shape& ver = expv.Current();
956
957         VertexExtrem = 1;
958         if (mapVerInt.IsBound(ver)) {
959           VertexExtrem = 0;
960         }
961         mapVerInt.Bind(ver,VertexExtrem);
962         
963       }
964     }
965
966     TopTools_ListOfShape myEdgeLV,myEdgeLMV;
967     for(itt2.Initialize(mapVerInt); itt2.More(); itt2.Next()) {
968       const TopoDS_Shape& ver = itt2.Key();
969       VertexExtrem =  mapVerInt.Find(ver);
970       if (VertexExtrem == 1) {
971         myEdgeLV.Append(ver);
972       }
973       else {
974 //      TopoDS_Shape& ver1 = ver.Oriented(TopAbs_INTERNAL);
975         const TopoDS_Shape& ver1 = ver.Oriented(TopAbs_INTERNAL);
976         myEdgeLMV.Append(ver1);
977       }
978     }
979     Standard_Integer number = myEdgeLV.Extent();
980     if (!(number == 2)){
981 #ifdef OCCT_DEBUG
982       if (trc) cout<<" TopOpeBRepBuild_FuseFace::MakeEdge : Failure in reconstructing new edge"<<endl;
983 #endif
984       return;
985     }
986     it.Initialize(myEdgeLV);
987     const TopoDS_Vertex& ver1 = TopoDS::Vertex(it.Value()); 
988 //    TopoDS_Shape& verf = ver1.Oriented(TopAbs_FORWARD); 
989     const TopoDS_Shape& verf = ver1.Oriented(TopAbs_FORWARD); 
990     it.Next();
991     const TopoDS_Vertex& ver2 = TopoDS::Vertex(it.Value());
992 //    TopoDS_Shape& verl = ver2.Oriented(TopAbs_FORWARD);
993     const TopoDS_Shape& verl = ver2.Oriented(TopAbs_FORWARD);
994
995     Handle(Geom_Curve) curv;
996     const TopoDS_Edge& edg = TopoDS::Edge(edg1);
997     TopLoc_Location loc;
998     Standard_Real first,last;
999     curv = BRep_Tool::Curve(edg,loc,first,last);
1000
1001     BRepLib_MakeEdge ME(curv,TopoDS::Vertex(verf),TopoDS::Vertex(verl));
1002     const TopoDS_Edge& edgnew = ME.Edge();
1003
1004 //    if (myInternal) {
1005 //      for (it.Initialize(myEdgeLMV); it.More(); it.Next()) {
1006 //      const TopoDS_Vertex& ver1 = TopoDS::Vertex(it.Value());
1007 //      BRep_Builder B;
1008 //      B.MakeEdge(edgnew);
1009 //      B.Add(edgnew,ver1);
1010 //      }
1011 //    }
1012     mapEdgLEdg.Bind(edgnew,LmapEdg);
1013     
1014   }
1015   mymapEdgLEdg = mapEdgLEdg;
1016 }
1017
1018 //=======================================================================
1019 //function : SameSupport
1020 //purpose  : Edges SameSupport ou pas
1021 //=======================================================================
1022
1023 Standard_Boolean SameSupport(const TopoDS_Edge& E1,
1024                              const TopoDS_Edge& E2)
1025 {
1026 #ifdef OCCT_DEBUG
1027   Standard_Boolean trc = TopOpeBRepBuild_GettraceFUFA();
1028 #endif
1029
1030   if (E1.IsNull() || E2.IsNull()) {
1031     return Standard_False;
1032   }
1033
1034
1035   Handle(Geom_Curve) C1,C2;
1036   TopLoc_Location loc;
1037   Standard_Real f1,l1,f2,l2;
1038   Handle(Standard_Type) typC1,typC2;
1039   
1040   C1 = BRep_Tool::Curve(E1,loc,f1,l1);
1041   if (!loc.IsIdentity()) {
1042     Handle(Geom_Geometry) GG1 = C1->Transformed(loc.Transformation());
1043     C1 = Handle(Geom_Curve)::DownCast (GG1);
1044   }
1045   C2 = BRep_Tool::Curve(E2,loc,f2,l2);
1046   if (!loc.IsIdentity()) {
1047     Handle(Geom_Geometry) GG2 = C2->Transformed(loc.Transformation());
1048     C2 = Handle(Geom_Curve)::DownCast (GG2);
1049   }
1050   
1051   typC1 = C1->DynamicType();
1052   typC2 = C2->DynamicType();
1053   
1054   if (typC1 == STANDARD_TYPE(Geom_TrimmedCurve)) {
1055     C1 =  Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
1056     typC1 = C1->DynamicType();
1057   }
1058   
1059   if (typC2 == STANDARD_TYPE(Geom_TrimmedCurve)) {
1060     C2 =  Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
1061     typC2 = C2->DynamicType();
1062   }
1063   
1064   if (typC1 != typC2) {
1065     return Standard_False;
1066   }
1067   
1068   if (typC1 != STANDARD_TYPE(Geom_Line) &&
1069       typC1 != STANDARD_TYPE(Geom_Circle) &&
1070       typC1 != STANDARD_TYPE(Geom_Ellipse) &&
1071       typC1 != STANDARD_TYPE(Geom_BSplineCurve) && 
1072       typC1 != STANDARD_TYPE(Geom_BezierCurve)) {
1073 #ifdef OCCT_DEBUG
1074     if (trc) cout << " TopOpeBRepBuild_FuseFace : Type de Support non traite" << endl;
1075 #endif
1076     return Standard_False;
1077   }
1078
1079   // On a presomption de confusion
1080   const Standard_Real tollin = Precision::Confusion();
1081   const Standard_Real tolang = Precision::Angular();
1082   if (typC1 == STANDARD_TYPE(Geom_Line)) {
1083     gp_Lin li1( Handle(Geom_Line)::DownCast (C1)->Lin());
1084     gp_Lin li2( Handle(Geom_Line)::DownCast (C2)->Lin());
1085     
1086     if (Abs(li1.Angle(li2)) <= tolang &&
1087         li1.Location().SquareDistance(li2.Location()) <= tollin*tollin) {
1088       return Standard_True;
1089     }
1090     return Standard_False;
1091   } 
1092   else if (typC1 == STANDARD_TYPE(Geom_Circle)) {
1093     gp_Circ ci1 = Handle(Geom_Circle)::DownCast (C1)->Circ();
1094     gp_Circ ci2 = Handle(Geom_Circle)::DownCast (C2)->Circ();
1095     if (Abs(ci1.Radius()-ci2.Radius()) <= tollin &&
1096         ci1.Location().SquareDistance(ci2.Location()) <= tollin*tollin) {
1097       // Point debut, calage dans periode, et detection meme sens
1098       return Standard_True;
1099     }
1100     return Standard_False;
1101   }
1102   else if (typC1 == STANDARD_TYPE(Geom_Ellipse)) {
1103     gp_Elips ci1 = Handle(Geom_Ellipse)::DownCast (C1)->Elips();
1104     gp_Elips ci2 = Handle(Geom_Ellipse)::DownCast (C2)->Elips();
1105     
1106     if (Abs(ci1.MajorRadius()-ci2.MajorRadius()) <= tollin &&
1107         Abs(ci1.MinorRadius()-ci2.MinorRadius()) <= tollin &&
1108         ci1.Location().SquareDistance(ci2.Location()) <= tollin*tollin) {
1109       // Point debut, calage dans periode, et detection meme sens
1110       return Standard_True;
1111     }
1112     return Standard_False;
1113   }
1114   else if (typC1 == STANDARD_TYPE(Geom_BSplineCurve)) {
1115     Handle(Geom_BSplineCurve) B1 = Handle(Geom_BSplineCurve)::DownCast (C1);
1116     Handle(Geom_BSplineCurve) B2 = Handle(Geom_BSplineCurve)::DownCast (C2);
1117    
1118     Standard_Integer nbpoles = B1->NbPoles();
1119     if (nbpoles != B2->NbPoles()) {
1120       return Standard_False;
1121     }
1122    
1123     Standard_Integer nbknots = B1->NbKnots();
1124     if (nbknots != B2->NbKnots()) {
1125       return Standard_False;
1126     }
1127    
1128     TColgp_Array1OfPnt P1(1, nbpoles), P2(1, nbpoles);
1129     B1->Poles(P1);
1130     B2->Poles(P2);
1131    
1132     Standard_Real tol3d = BRep_Tool::Tolerance(E1);
1133     for (Standard_Integer p = 1; p <= nbpoles; p++) {
1134       if ( (P1(p)).Distance(P2(p)) > tol3d) {
1135         return Standard_False;
1136       }
1137     }
1138    
1139     TColStd_Array1OfReal K1(1, nbknots), K2(1, nbknots);
1140     B1->Knots(K1);
1141     B2->Knots(K2);
1142    
1143     TColStd_Array1OfInteger M1(1, nbknots), M2(1, nbknots);
1144     B1->Multiplicities(M1);
1145     B2->Multiplicities(M2);
1146    
1147     for (Standard_Integer k = 1; k <= nbknots; k++) {
1148       if ((K1(k)-K2(k)) > tollin) {
1149         return Standard_False;
1150       }
1151       if (Abs(M1(k)-M2(k)) > tollin) {
1152         return Standard_False;
1153       }
1154     }
1155    
1156     if (!B1->IsRational()) {
1157       if (B2->IsRational()) {
1158         return Standard_False;
1159       }
1160     }
1161     else {
1162       if (!B2->IsRational()) {
1163         return Standard_False;
1164       }
1165     }
1166     
1167     if (B1->IsRational()) {
1168       TColStd_Array1OfReal W1(1, nbpoles), W2(1, nbpoles);
1169       B1->Weights(W1);
1170       B2->Weights(W2);
1171    
1172       for (Standard_Integer w = 1; w <= nbpoles; w++) {
1173         if (Abs(W1(w)-W2(w)) > tollin) {
1174           return Standard_False;
1175         }
1176       }
1177     }
1178     return Standard_True;
1179   }
1180   else if (typC1 == STANDARD_TYPE(Geom_BezierCurve)) {
1181     Handle(Geom_BezierCurve) B1 = Handle(Geom_BezierCurve)::DownCast (C1);
1182     Handle(Geom_BezierCurve) B2 = Handle(Geom_BezierCurve)::DownCast (C2);
1183     
1184     Standard_Integer nbpoles = B1->NbPoles();
1185     if (nbpoles != B2->NbPoles()) {
1186       return Standard_False;
1187     }
1188     
1189     TColgp_Array1OfPnt P1(1, nbpoles), P2(1, nbpoles);
1190     B1->Poles(P1);
1191     B2->Poles(P2);
1192     
1193     for (Standard_Integer p = 1; p <= nbpoles; p++) {
1194       if ( (P1(p)).Distance(P2(p)) > tollin) {
1195         return Standard_False;
1196       }
1197     }
1198     
1199     if (!B1->IsRational()) {
1200       if (B2->IsRational()) {
1201         return Standard_False;
1202       }
1203     }
1204     else {
1205       if (!B2->IsRational()) {
1206         return Standard_False;
1207       }
1208     }
1209     
1210     if (B1->IsRational()) {
1211       TColStd_Array1OfReal W1(1, nbpoles), W2(1, nbpoles);
1212       B1->Weights(W1);
1213       B2->Weights(W2);
1214       
1215       for (Standard_Integer w = 1; w <= nbpoles; w++) {
1216         if (Abs(W1(w)-W2(w)) > tollin) {
1217           return Standard_False;
1218         }
1219       }
1220     }
1221     return Standard_True;
1222   }
1223   return Standard_False;
1224 }