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