0025592: Bad result of Fillet operation
[occt.git] / src / BRepTools / BRepTools.cxx
1 // Created on: 1993-01-21
2 // Created by: Remi LEQUETTE
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 #include <Standard_Stream.hxx>
18
19 #include <BRepTools.ixx>
20 #include <BRepTools_ShapeSet.hxx>
21 #include <BRep_Tool.hxx>
22 #include <TopExp.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Iterator.hxx>
26 #include <BndLib_Add2dCurve.hxx>
27 #include <Geom2dAdaptor_Curve.hxx>
28 #include <Geom_Surface.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom2d_Curve.hxx>
31 #include <BRepTools_MapOfVertexPnt2d.hxx>
32 #include <BRep_CurveRepresentation.hxx>
33 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
34 #include <BRep_TEdge.hxx>
35 #include <TColgp_SequenceOfPnt2d.hxx>
36 #include <TColStd_SequenceOfReal.hxx>
37 #include <TColStd_Array1OfReal.hxx>
38 #include <TColGeom2d_SequenceOfCurve.hxx>
39 #include <TopTools_SequenceOfShape.hxx>
40 #include <Precision.hxx>
41
42 #include <Poly_Triangulation.hxx>
43 #include <Poly_PolygonOnTriangulation.hxx>
44 #include <TColStd_HArray1OfInteger.hxx>
45 #include <TColStd_MapOfTransient.hxx>
46
47 #include <gp_Lin2d.hxx>
48 #include <ElCLib.hxx>
49 #include <gp_Vec2d.hxx>
50 #include <Standard_ErrorHandler.hxx>
51 #include <Standard_Failure.hxx>
52 #include <Geom_RectangularTrimmedSurface.hxx>
53 #include <OSD_OpenFile.hxx>
54
55 #include <errno.h>
56
57 //=======================================================================
58 //function : UVBounds
59 //purpose  : 
60 //=======================================================================
61
62 void  BRepTools::UVBounds(const TopoDS_Face& F, 
63                           Standard_Real& UMin, Standard_Real& UMax, 
64                           Standard_Real& VMin, Standard_Real& VMax)
65 {
66   Bnd_Box2d B;
67   AddUVBounds(F,B);
68   B.Get(UMin,VMin,UMax,VMax);
69 }
70
71 //=======================================================================
72 //function : UVBounds
73 //purpose  : 
74 //=======================================================================
75
76 void  BRepTools::UVBounds(const TopoDS_Face& F,
77                           const TopoDS_Wire& W, 
78                           Standard_Real& UMin, Standard_Real& UMax, 
79                           Standard_Real& VMin, Standard_Real& VMax)
80 {
81   Bnd_Box2d B;
82   AddUVBounds(F,W,B);
83   B.Get(UMin,VMin,UMax,VMax);
84 }
85
86
87 //=======================================================================
88 //function : UVBounds
89 //purpose  : 
90 //=======================================================================
91
92 void  BRepTools::UVBounds(const TopoDS_Face& F,
93                           const TopoDS_Edge& E, 
94                           Standard_Real& UMin, Standard_Real& UMax, 
95                           Standard_Real& VMin, Standard_Real& VMax)
96 {
97   Bnd_Box2d B;
98   AddUVBounds(F,E,B);
99   B.Get(UMin,VMin,UMax,VMax);
100 }
101
102 //=======================================================================
103 //function : AddUVBounds
104 //purpose  : 
105 //=======================================================================
106
107 void  BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B)
108 {
109   TopoDS_Face F = FF;
110   F.Orientation(TopAbs_FORWARD);
111   TopExp_Explorer ex(F,TopAbs_EDGE);
112
113   // fill box for the given face
114   Bnd_Box2d aBox;
115   for (;ex.More();ex.Next()) {
116     BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),aBox);
117   }
118   
119   // if the box is empty (face without edges or without pcurves),
120   // get natural bounds
121   if (aBox.IsVoid()) {
122     Standard_Real UMin,UMax,VMin,VMax;
123     TopLoc_Location L;
124     BRep_Tool::Surface(F,L)->Bounds(UMin,UMax,VMin,VMax);
125     aBox.Update(UMin,VMin,UMax,VMax);
126   }
127   
128   // add face box to result
129   B.Add ( aBox );
130 }
131
132
133 //=======================================================================
134 //function : AddUVBounds
135 //purpose  : 
136 //=======================================================================
137 void  BRepTools::AddUVBounds(const TopoDS_Face& F, 
138                              const TopoDS_Wire& W, 
139                              Bnd_Box2d& B)
140 {
141   TopExp_Explorer ex;
142   for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) {
143     BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),B);
144     }
145 }
146
147
148 //=======================================================================
149 //function : AddUVBounds
150 //purpose  : 
151 //=======================================================================
152 void BRepTools::AddUVBounds(const TopoDS_Face& aF, 
153                             const TopoDS_Edge& aE,
154                             Bnd_Box2d& aB)
155 {
156   Standard_Real aT1, aT2, aXmin, aYmin, aXmax, aYmax;
157   Standard_Real aUmin, aUmax, aVmin, aVmax;
158   Bnd_Box2d aBoxC, aBoxS; 
159   TopLoc_Location aLoc;
160   //
161   const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
162   if (aC2D.IsNull()) {
163     return;
164   }
165   //
166   BndLib_Add2dCurve::Add(aC2D, aT1, aT2, 0., aBoxC);
167   aBoxC.Get(aXmin, aYmin, aXmax, aYmax);
168   //
169   Handle(Geom_Surface) aS = BRep_Tool::Surface(aF, aLoc);
170   aS->Bounds(aUmin, aUmax, aVmin, aVmax);
171
172   if(aS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
173   {
174     const Handle(Geom_RectangularTrimmedSurface) aSt = 
175                 Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
176     aS = aSt->BasisSurface();
177   }
178
179   //
180   if(!aS->IsUPeriodic())
181   {
182     if((aXmin<aUmin) && (aUmin < aXmax))
183     {
184       aXmin=aUmin;
185     }
186     if((aXmin < aUmax) && (aUmax < aXmax))
187     {
188       aXmax=aUmax;
189     }
190   }
191
192   if(!aS->IsVPeriodic())
193   {
194     if((aYmin<aVmin) && (aVmin < aYmax))
195     {
196       aYmin=aVmin;
197     }
198     
199     if((aYmin < aVmax) && (aVmax < aYmax))
200     {
201       aYmax=aVmax;
202     }
203   }
204   
205   aBoxS.Update(aXmin, aYmin, aXmax, aYmax);
206   
207   aB.Add(aBoxS);
208 }
209
210 //=======================================================================
211 //function : Update
212 //purpose  : 
213 //=======================================================================
214
215 void BRepTools::Update(const TopoDS_Vertex&)
216 {
217 }
218
219 //=======================================================================
220 //function : Update
221 //purpose  : 
222 //=======================================================================
223
224 void BRepTools::Update(const TopoDS_Edge&)
225 {
226 }
227
228 //=======================================================================
229 //function : Update
230 //purpose  : 
231 //=======================================================================
232
233 void BRepTools::Update(const TopoDS_Wire&)
234 {
235 }
236
237 //=======================================================================
238 //function : Update
239 //purpose  : 
240 //=======================================================================
241
242 void BRepTools::Update(const TopoDS_Face& F)
243 {
244   if (!F.Checked()) {
245     UpdateFaceUVPoints(F);
246     F.TShape()->Checked(Standard_True);
247   }
248 }
249
250 //=======================================================================
251 //function : Update
252 //purpose  : 
253 //=======================================================================
254
255 void BRepTools::Update(const TopoDS_Shell& S)
256 {
257   TopExp_Explorer ex(S,TopAbs_FACE);
258   while (ex.More()) {
259     Update(TopoDS::Face(ex.Current()));
260     ex.Next();
261   }
262 }
263
264 //=======================================================================
265 //function : Update
266 //purpose  : 
267 //=======================================================================
268
269 void BRepTools::Update(const TopoDS_Solid& S)
270 {
271   TopExp_Explorer ex(S,TopAbs_FACE);
272   while (ex.More()) {
273     Update(TopoDS::Face(ex.Current()));
274     ex.Next();
275   }
276 }
277
278 //=======================================================================
279 //function : Update
280 //purpose  : 
281 //=======================================================================
282
283 void BRepTools::Update(const TopoDS_CompSolid& CS)
284 {
285   TopExp_Explorer ex(CS,TopAbs_FACE);
286   while (ex.More()) {
287     Update(TopoDS::Face(ex.Current()));
288     ex.Next();
289   }
290 }
291
292 //=======================================================================
293 //function : Update
294 //purpose  : 
295 //=======================================================================
296
297 void BRepTools::Update(const TopoDS_Compound& C)
298 {
299   TopExp_Explorer ex(C,TopAbs_FACE);
300   while (ex.More()) {
301     Update(TopoDS::Face(ex.Current()));
302     ex.Next();
303   }
304 }
305
306 //=======================================================================
307 //function : Update
308 //purpose  : 
309 //=======================================================================
310
311 void BRepTools::Update(const TopoDS_Shape& S)
312 {
313   switch (S.ShapeType()) {
314
315   case TopAbs_VERTEX :
316     Update(TopoDS::Vertex(S));
317     break;
318
319   case TopAbs_EDGE :
320     Update(TopoDS::Edge(S));
321     break;
322
323   case TopAbs_WIRE :
324     Update(TopoDS::Wire(S));
325     break;
326
327   case TopAbs_FACE :
328     Update(TopoDS::Face(S));
329     break;
330
331   case TopAbs_SHELL :
332     Update(TopoDS::Shell(S));
333     break;
334
335   case TopAbs_SOLID :
336     Update(TopoDS::Solid(S));
337     break;
338
339   case TopAbs_COMPSOLID :
340     Update(TopoDS::CompSolid(S));
341     break;
342
343   case TopAbs_COMPOUND :
344     Update(TopoDS::Compound(S));
345     break;
346
347   default:
348     break;
349
350   }
351 }
352
353
354 //=======================================================================
355 //function : UpdateFaceUVPoints
356 //purpose  : reset the UV points of a  Face
357 //=======================================================================
358
359 void  BRepTools::UpdateFaceUVPoints(const TopoDS_Face& F)
360 {
361   // Recompute for each edge the two UV points in order to have the same
362   // UV point on connected edges.
363
364   // First edge loop, store the vertices in a Map with their 2d points
365
366   BRepTools_MapOfVertexPnt2d theVertices;
367   TopoDS_Iterator expE,expV;
368   TopoDS_Iterator EdgeIt,VertIt;
369   TColStd_SequenceOfReal aFSeq, aLSeq;
370   TColGeom2d_SequenceOfCurve aCSeq;
371   TopTools_SequenceOfShape aShSeq;
372   gp_Pnt2d P;
373   Standard_Integer i;
374   // a 3d tolerance for UV !!
375   Standard_Real tolerance = BRep_Tool::Tolerance(F);
376   TColgp_SequenceOfPnt2d emptySequence;
377   
378   for (expE.Initialize(F); expE.More(); expE.Next()) {
379     if(expE.Value().ShapeType() != TopAbs_WIRE)
380       continue;
381     
382     EdgeIt.Initialize(expE.Value());
383     for( ; EdgeIt.More(); EdgeIt.Next())
384     {
385       const TopoDS_Edge& E = TopoDS::Edge(EdgeIt.Value());
386       Standard_Real f,l;
387       Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l);
388
389       aFSeq.Append(f);
390       aLSeq.Append(l);
391       aCSeq.Append(C);
392       aShSeq.Append(E);
393
394       if (C.IsNull()) continue;
395
396       for (expV.Initialize(E.Oriented(TopAbs_FORWARD)); 
397            expV.More(); expV.Next()) {
398         
399         const TopoDS_Vertex& V = TopoDS::Vertex(expV.Value());
400         
401         TopAbs_Orientation Vori = V.Orientation();
402         if ( Vori == TopAbs_INTERNAL ) {
403           continue;
404         }
405         
406         Standard_Real p = BRep_Tool::Parameter(V,E,F);
407         C->D0(p,P);
408         if (!theVertices.IsBound(V)) 
409           theVertices.Bind(V,emptySequence);
410         TColgp_SequenceOfPnt2d& S = theVertices(V);
411         for (i = 1; i <= S.Length(); i++) {
412           if (P.Distance(S(i)) < tolerance) break;
413         }
414         if (i > S.Length())
415           S.Append(P);
416       }
417     }
418   }
419  
420   // second edge loop, update the edges 2d points
421   TopoDS_Vertex Vf,Vl;
422   gp_Pnt2d Pf,Pl;
423
424   for(Standard_Integer j = 1; j <= aShSeq.Length(); j++)
425   {
426     const TopoDS_Edge& E = TopoDS::Edge(aShSeq.Value(j));
427     const Handle(Geom2d_Curve)& C = aCSeq.Value(j);
428     if (C.IsNull()) continue;
429     
430     TopExp::Vertices(E,Vf,Vl);
431     if (Vf.IsNull()) {
432       Pf.SetCoord(RealLast(),RealLast());
433     }
434     else {
435       if ( Vf.Orientation() == TopAbs_INTERNAL ) {
436         continue;
437       }
438       const TColgp_SequenceOfPnt2d& seqf = theVertices(Vf);
439       if (seqf.Length() == 1) 
440         Pf = seqf(1);
441       else {
442         C->D0(aFSeq.Value(j),Pf);
443         for (i = 1; i <= seqf.Length(); i++) {
444           if (Pf.Distance(seqf(i)) <= tolerance) {
445             Pf = seqf(i);
446             break;
447           }
448         }
449       }
450     }
451     if (Vl.IsNull()) {
452       Pl.SetCoord(RealLast(),RealLast());
453     }
454     else {
455       if ( Vl.Orientation() == TopAbs_INTERNAL ) {
456         continue;
457       }
458       const TColgp_SequenceOfPnt2d& seql = theVertices(Vl);
459       if (seql.Length() == 1) 
460         Pl = seql(1);
461       else {
462         C->D0(aLSeq.Value(j),Pl);
463         for (i = 1; i <= seql.Length(); i++) {
464           if (Pl.Distance(seql(i)) <= tolerance) {
465             Pl = seql(i);
466             break;
467           }
468         }
469       }
470     }
471
472     // set the correct points
473     BRep_Tool::SetUVPoints(E,F,Pf,Pl);
474   }
475 }
476
477
478
479 //=======================================================================
480 //function : Compare
481 //purpose  : 
482 //=======================================================================
483
484 Standard_Boolean BRepTools::Compare(const TopoDS_Vertex& V1,
485                                     const TopoDS_Vertex& V2)
486 {
487   if (V1.IsSame(V2)) return Standard_True;
488   gp_Pnt p1 = BRep_Tool::Pnt(V1);
489   gp_Pnt p2 = BRep_Tool::Pnt(V2);
490   Standard_Real l = p1.Distance(p2);
491   if (l <= BRep_Tool::Tolerance(V1)) return Standard_True;
492   if (l <= BRep_Tool::Tolerance(V2)) return Standard_True;
493   return Standard_False;
494 }
495
496 //=======================================================================
497 //function : Compare
498 //purpose  : 
499 //=======================================================================
500
501 Standard_Boolean BRepTools::Compare(const TopoDS_Edge& E1,
502                                     const TopoDS_Edge& E2)
503 {
504   if (E1.IsSame(E2)) return Standard_True;
505   return Standard_False;
506 }
507
508 //=======================================================================
509 //function : OuterWire
510 //purpose  : 
511 //=======================================================================
512
513 TopoDS_Wire  BRepTools::OuterWire(const TopoDS_Face& F)
514 {
515   TopoDS_Wire Wres;
516   TopExp_Explorer expw (F,TopAbs_WIRE);
517
518   if (expw.More()) {
519     Wres = TopoDS::Wire(expw.Current());
520     expw.Next();
521     if (expw.More()) {
522       Standard_Real UMin, UMax, VMin, VMax;
523       Standard_Real umin, umax, vmin, vmax;
524       BRepTools::UVBounds(F,Wres,UMin,UMax,VMin,VMax);
525         while (expw.More()) {
526           const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
527           BRepTools::UVBounds(F,W,umin, umax, vmin, vmax);
528           if ((umin <= UMin) &&
529               (umax >= UMax) &&
530               (vmin <= VMin) &&
531               (vmax >= VMax)) {
532             Wres = W;
533             UMin = umin;
534             UMax = umax;
535             VMin = vmin;
536             VMax = vmax;
537           }
538           expw.Next();
539         }
540     }
541   }
542   return Wres;
543 }
544
545 //=======================================================================
546 //function : Map3DEdges
547 //purpose  : 
548 //=======================================================================
549
550 void  BRepTools::Map3DEdges(const TopoDS_Shape& S, 
551                             TopTools_IndexedMapOfShape& M)
552 {
553   TopExp_Explorer Ex;
554   for (Ex.Init(S,TopAbs_EDGE); Ex.More(); Ex.Next()) {
555     if (!BRep_Tool::Degenerated(TopoDS::Edge(Ex.Current())))
556       M.Add(Ex.Current());
557   }
558 }
559
560 //=======================================================================
561 //function : Dump
562 //purpose  : 
563 //=======================================================================
564
565 void  BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
566 {
567   BRepTools_ShapeSet SS;
568   SS.Add(Sh);
569   SS.Dump(Sh,S);
570   SS.Dump(S);
571 }
572
573 //=======================================================================
574 //function : Write
575 //purpose  : 
576 //=======================================================================
577
578 void  BRepTools::Write(const TopoDS_Shape& Sh, Standard_OStream& S,
579                        const Handle(Message_ProgressIndicator)& PR)
580 {
581   BRepTools_ShapeSet SS;
582   SS.SetProgress(PR);
583   SS.Add(Sh);
584   SS.Write(S);
585   SS.Write(Sh,S);
586 }
587
588
589 //=======================================================================
590 //function : Read
591 //purpose  : 
592 //=======================================================================
593
594 void  BRepTools::Read(TopoDS_Shape& Sh, 
595                       istream& S, 
596                       const BRep_Builder& B,
597                       const Handle(Message_ProgressIndicator)& PR)
598 {
599   BRepTools_ShapeSet SS(B);
600   SS.SetProgress(PR);
601   SS.Read(S);
602   SS.Read(Sh,S);
603 }
604
605 //=======================================================================
606 //function : Write
607 //purpose  : 
608 //=======================================================================
609
610 Standard_Boolean  BRepTools::Write(const TopoDS_Shape& Sh, 
611                                    const Standard_CString File,
612                                    const Handle(Message_ProgressIndicator)& PR)
613 {
614   ofstream os;
615   OSD_OpenStream(os, File, ios::out);
616   if (!os.rdbuf()->is_open()) return Standard_False;
617
618   Standard_Boolean isGood = (os.good() && !os.eof());
619   if(!isGood)
620     return isGood;
621   
622   BRepTools_ShapeSet SS;
623   SS.SetProgress(PR);
624   SS.Add(Sh);
625   
626   os << "DBRep_DrawableShape\n";  // for easy Draw read
627   SS.Write(os);
628   isGood = os.good();
629   if(isGood )
630     SS.Write(Sh,os);
631   os.flush();
632   isGood = os.good();
633
634   errno = 0;
635   os.close();
636   isGood = os.good() && isGood && !errno;
637
638   return isGood;
639 }
640
641 //=======================================================================
642 //function : Read
643 //purpose  : 
644 //=======================================================================
645
646 Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh, 
647                                  const Standard_CString File,
648                                  const BRep_Builder& B,
649                                  const Handle(Message_ProgressIndicator)& PR)
650 {
651   filebuf fic;
652   istream in(&fic);
653   OSD_OpenFileBuf(fic,File,ios::in);
654   if(!fic.is_open()) return Standard_False;
655   
656   BRepTools_ShapeSet SS(B);
657   SS.SetProgress(PR);
658   SS.Read(in);
659   if(!SS.NbShapes()) return Standard_False;
660   SS.Read(Sh,in);
661   return Standard_True;
662 }
663
664
665 //=======================================================================
666 //function : Clean
667 //purpose  : 
668 //=======================================================================
669
670 void BRepTools::Clean(const TopoDS_Shape& theShape)
671 {
672   BRep_Builder aBuilder;
673   Handle(Poly_Triangulation) aNullTriangulation;
674   Handle(Poly_PolygonOnTriangulation) aNullPoly;
675
676   if (theShape.IsNull())
677     return;
678
679   TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
680   for (; aFaceIt.More(); aFaceIt.Next())
681   {
682     const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
683
684     TopLoc_Location aLoc;
685     const Handle(Poly_Triangulation)& aTriangulation =
686       BRep_Tool::Triangulation(aFace, aLoc);
687
688     if (aTriangulation.IsNull())
689       continue;
690
691     // Nullify edges
692     TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE);
693     for (; aEdgeIt.More(); aEdgeIt.Next())
694     {
695       const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
696       aBuilder.UpdateEdge(aEdge, aNullPoly, aTriangulation, aLoc);
697     }
698
699     aBuilder.UpdateFace(aFace, aNullTriangulation);
700   }
701 }
702
703 //=======================================================================
704 //function : RemoveUnusedPCurves
705 //purpose  : 
706 //=======================================================================
707
708 void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S)
709 {
710   TColStd_MapOfTransient UsedSurfaces;
711   
712   TopExp_Explorer Explo(S, TopAbs_FACE);
713   for (; Explo.More(); Explo.Next())
714   {
715     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
716     TopLoc_Location aLoc;
717     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
718     UsedSurfaces.Add(aSurf);
719   }
720
721   TopTools_IndexedMapOfShape Emap;
722   TopExp::MapShapes(S, TopAbs_EDGE, Emap);
723
724   Standard_Integer i;
725   for (i = 1; i <= Emap.Extent(); i++)
726   {
727     const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape());
728     BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves();
729     BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr );
730     while (itrep.More())
731     {
732       Standard_Boolean ToRemove = Standard_False;
733       
734       Handle(BRep_CurveRepresentation) CurveRep = itrep.Value();
735       if (CurveRep->IsCurveOnSurface())
736       {
737         Handle(Geom_Surface) aSurface = CurveRep->Surface();
738         if (!UsedSurfaces.Contains(aSurface))
739           ToRemove = Standard_True;
740       }
741       else if (CurveRep->IsRegularity())
742       {
743         Handle(Geom_Surface) Surf1 = CurveRep->Surface();
744         Handle(Geom_Surface) Surf2 = CurveRep->Surface2();
745         ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2));
746       }
747       
748       if (ToRemove)
749         lcr.Remove(itrep);
750       else
751         itrep.Next();
752     }
753   }
754 }
755
756 //=======================================================================
757 //function : Triangulation
758 //purpose  : 
759 //=======================================================================
760
761 Standard_Boolean  BRepTools::Triangulation(const TopoDS_Shape&    S,
762                                            const Standard_Real    deflec)
763 {
764   TopExp_Explorer exf, exe;
765   TopLoc_Location l;
766   Handle(Poly_Triangulation) T;
767   Handle(Poly_PolygonOnTriangulation) Poly;
768
769   for (exf.Init(S, TopAbs_FACE); exf.More(); exf.Next()) {
770     const TopoDS_Face& F = TopoDS::Face(exf.Current());
771     T = BRep_Tool::Triangulation(F, l);
772     if (T.IsNull() || (T->Deflection() > deflec))
773       return Standard_False;
774     for (exe.Init(F, TopAbs_EDGE); exe.More(); exe.Next()) {
775       const TopoDS_Edge& E = TopoDS::Edge(exe.Current());
776       Poly = BRep_Tool::PolygonOnTriangulation(E, T, l);
777       if (Poly.IsNull()) return Standard_False;
778     }
779   }
780   return Standard_True;
781 }
782
783
784 //=======================================================================
785 //function : IsReallyClosed
786 //purpose  : 
787 //=======================================================================
788
789 Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
790                                            const TopoDS_Face& F)
791 {
792   if (!BRep_Tool::IsClosed(E,F)) {
793     return Standard_False;
794   }
795   Standard_Integer nbocc = 0;
796   TopExp_Explorer exp;
797   for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) {
798     if (exp.Current().IsSame(E)) {
799       nbocc++;
800     }
801   }
802   return nbocc == 2;
803 }
804
805
806