0027821: Visualization, AIS_Shape - add NULL checks for displaying TopoDS_Face with...
[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
18 #include <Bnd_Box2d.hxx>
19 #include <BndLib_Add2dCurve.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRep_CurveRepresentation.hxx>
22 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
23 #include <BRep_TEdge.hxx>
24 #include <BRep_Tool.hxx>
25 #include <BRepTools.hxx>
26 #include <BRepTools_MapOfVertexPnt2d.hxx>
27 #include <BRepTools_ShapeSet.hxx>
28 #include <ElCLib.hxx>
29 #include <Geom2d_Curve.hxx>
30 #include <Geom2dAdaptor_Curve.hxx>
31 #include <Geom_BSplineSurface.hxx>
32 #include <Geom_Curve.hxx>
33 #include <Geom_RectangularTrimmedSurface.hxx>
34 #include <Geom_Surface.hxx>
35 #include <gp_Lin2d.hxx>
36 #include <gp_Vec2d.hxx>
37 #include <Message_ProgressIndicator.hxx>
38 #include <OSD_OpenFile.hxx>
39 #include <Poly_PolygonOnTriangulation.hxx>
40 #include <Poly_Triangulation.hxx>
41 #include <Precision.hxx>
42 #include <Standard_ErrorHandler.hxx>
43 #include <Standard_Failure.hxx>
44 #include <Standard_Stream.hxx>
45 #include <TColGeom2d_SequenceOfCurve.hxx>
46 #include <TColgp_SequenceOfPnt2d.hxx>
47 #include <TColStd_Array1OfReal.hxx>
48 #include <TColStd_HArray1OfInteger.hxx>
49 #include <TColStd_MapOfTransient.hxx>
50 #include <TColStd_SequenceOfReal.hxx>
51 #include <TopExp.hxx>
52 #include <TopExp_Explorer.hxx>
53 #include <TopoDS.hxx>
54 #include <TopoDS_Compound.hxx>
55 #include <TopoDS_CompSolid.hxx>
56 #include <TopoDS_Edge.hxx>
57 #include <TopoDS_Face.hxx>
58 #include <TopoDS_Iterator.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Shell.hxx>
61 #include <TopoDS_Solid.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <TopoDS_Wire.hxx>
64 #include <TopTools_SequenceOfShape.hxx>
65 #include <GeomLib_CheckCurveOnSurface.hxx>
66 #include <errno.h>
67 //=======================================================================
68 //function : UVBounds
69 //purpose  : 
70 //=======================================================================
71 void  BRepTools::UVBounds(const TopoDS_Face& F, 
72                           Standard_Real& UMin, Standard_Real& UMax, 
73                           Standard_Real& VMin, Standard_Real& VMax)
74 {
75   Bnd_Box2d B;
76   AddUVBounds(F,B);
77   if (!B.IsVoid())
78   {
79     B.Get(UMin,VMin,UMax,VMax);
80   }
81   else
82   {
83     UMin = UMax = VMin = VMax = 0.0;
84   }
85 }
86
87 //=======================================================================
88 //function : UVBounds
89 //purpose  : 
90 //=======================================================================
91
92 void  BRepTools::UVBounds(const TopoDS_Face& F,
93                           const TopoDS_Wire& W, 
94                           Standard_Real& UMin, Standard_Real& UMax, 
95                           Standard_Real& VMin, Standard_Real& VMax)
96 {
97   Bnd_Box2d B;
98   AddUVBounds(F,W,B);
99   if (!B.IsVoid())
100   {
101     B.Get(UMin,VMin,UMax,VMax);
102   }
103   else
104   {
105     UMin = UMax = VMin = VMax = 0.0;
106   }
107 }
108
109
110 //=======================================================================
111 //function : UVBounds
112 //purpose  : 
113 //=======================================================================
114
115 void  BRepTools::UVBounds(const TopoDS_Face& F,
116                           const TopoDS_Edge& E, 
117                           Standard_Real& UMin, Standard_Real& UMax, 
118                           Standard_Real& VMin, Standard_Real& VMax)
119 {
120   Bnd_Box2d B;
121   AddUVBounds(F,E,B);
122   if (!B.IsVoid())
123   {
124     B.Get(UMin,VMin,UMax,VMax);
125   }
126   else
127   {
128     UMin = UMax = VMin = VMax = 0.0;
129   }
130 }
131
132 //=======================================================================
133 //function : AddUVBounds
134 //purpose  : 
135 //=======================================================================
136
137 void  BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B)
138 {
139   TopoDS_Face F = FF;
140   F.Orientation(TopAbs_FORWARD);
141   TopExp_Explorer ex(F,TopAbs_EDGE);
142
143   // fill box for the given face
144   Bnd_Box2d aBox;
145   for (;ex.More();ex.Next()) {
146     BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),aBox);
147   }
148   
149   // if the box is empty (face without edges or without pcurves),
150   // get natural bounds
151   if (aBox.IsVoid()) {
152     Standard_Real UMin,UMax,VMin,VMax;
153     TopLoc_Location L;
154     const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, L);
155     if (aSurf.IsNull())
156     {
157       return;
158     }
159
160     aSurf->Bounds(UMin,UMax,VMin,VMax);
161     aBox.Update(UMin,VMin,UMax,VMax);
162   }
163   
164   // add face box to result
165   B.Add ( aBox );
166 }
167
168
169 //=======================================================================
170 //function : AddUVBounds
171 //purpose  : 
172 //=======================================================================
173 void  BRepTools::AddUVBounds(const TopoDS_Face& F, 
174                              const TopoDS_Wire& W, 
175                              Bnd_Box2d& B)
176 {
177   TopExp_Explorer ex;
178   for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) {
179     BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),B);
180     }
181 }
182
183
184 //=======================================================================
185 //function : AddUVBounds
186 //purpose  : 
187 //=======================================================================
188 void BRepTools::AddUVBounds(const TopoDS_Face& aF, 
189                             const TopoDS_Edge& aE,
190                             Bnd_Box2d& aB)
191 {
192   Standard_Real aT1, aT2, aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0;
193   Standard_Real aUmin, aUmax, aVmin, aVmax;
194   Bnd_Box2d aBoxC, aBoxS; 
195   TopLoc_Location aLoc;
196   //
197   const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
198   if (aC2D.IsNull()) {
199     return;
200   }
201   //
202   BndLib_Add2dCurve::Add(aC2D, aT1, aT2, 0., aBoxC);
203   if (!aBoxC.IsVoid())
204   {
205     aBoxC.Get(aXmin, aYmin, aXmax, aYmax);
206   }
207   //
208   Handle(Geom_Surface) aS = BRep_Tool::Surface(aF, aLoc);
209   aS->Bounds(aUmin, aUmax, aVmin, aVmax);
210
211   if(aS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
212   {
213     const Handle(Geom_RectangularTrimmedSurface) aSt = 
214                 Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
215     aS = aSt->BasisSurface();
216   }
217
218   //
219   if(!aS->IsUPeriodic())
220   {
221     Standard_Boolean isUPeriodic = Standard_False;
222
223     // Additional verification for U-periodicity for B-spline surfaces
224     // 1. Verify that the surface is U-closed (if such flag is false). Verification uses 2 points
225     // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points.
226     if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) &&
227         (aXmin < aUmin || aXmax > aUmax))
228     {
229       Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
230       isUPeriodic = Standard_True;
231       gp_Pnt P1, P2;
232       // 1. Verify that the surface is U-closed
233       if (!aS->IsUClosed())
234       {
235         Standard_Real aVStep = aVmax - aVmin;
236         for (Standard_Real aV = aVmin; aV <= aVmax; aV += aVStep)
237         {
238           P1 = aS->Value(aUmin, aV);
239           P2 = aS->Value(aUmax, aV);
240           if (P1.SquareDistance(P2) > aTol2)
241           {
242             isUPeriodic = Standard_False;
243             break;
244           }
245         }
246       }
247       // 2. Verify periodicity of surface inside UV-bounds of the edge
248       if (isUPeriodic) // the flag still not changed
249       {
250         Standard_Real aV = (aVmin + aVmax) * 0.5;
251         Standard_Real aU[6]; // values of U lying out of surface boundaries
252         Standard_Real aUpp[6]; // corresponding U-values plus/minus period
253         Standard_Integer aNbPnt = 0;
254         if (aXmin < aUmin)
255         {
256           aU[0] = aXmin;
257           aU[1] = (aXmin + aUmin) * 0.5;
258           aU[2] = aUmin;
259           aUpp[0] = aU[0] + aUmax - aUmin;
260           aUpp[1] = aU[1] + aUmax - aUmin;
261           aUpp[2] = aU[2] + aUmax - aUmin;
262           aNbPnt += 3;
263         }
264         if (aXmax > aUmax)
265         {
266           aU[aNbPnt]     = aUmax;
267           aU[aNbPnt + 1] = (aXmax + aUmax) * 0.5;
268           aU[aNbPnt + 2] = aXmax;
269           aUpp[aNbPnt]     = aU[aNbPnt] - aUmax + aUmin;
270           aUpp[aNbPnt + 1] = aU[aNbPnt + 1] - aUmax + aUmin;
271           aUpp[aNbPnt + 2] = aU[aNbPnt + 2] - aUmax + aUmin;
272           aNbPnt += 3;
273         }
274         for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
275         {
276           P1 = aS->Value(aU[anInd], aV);
277           P2 = aS->Value(aUpp[anInd], aV);
278           if (P1.SquareDistance(P2) > aTol2)
279           {
280             isUPeriodic = Standard_False;
281             break;
282           }
283         }
284       }
285     }
286
287     if (!isUPeriodic)
288     {
289       if((aXmin<aUmin) && (aUmin < aXmax))
290       {
291         aXmin=aUmin;
292       }
293       if((aXmin < aUmax) && (aUmax < aXmax))
294       {
295         aXmax=aUmax;
296       }
297     }
298   }
299
300   if(!aS->IsVPeriodic())
301   {
302     Standard_Boolean isVPeriodic = Standard_False;
303
304     // Additional verification for V-periodicity for B-spline surfaces
305     // 1. Verify that the surface is V-closed (if such flag is false). Verification uses 2 points
306     // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points.
307     if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) &&
308         (aYmin < aVmin || aYmax > aVmax))
309     {
310       Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
311       isVPeriodic = Standard_True;
312       gp_Pnt P1, P2;
313       // 1. Verify that the surface is V-closed
314       if (!aS->IsVClosed())
315       {
316         Standard_Real aUStep = aUmax - aUmin;
317         for (Standard_Real aU = aUmin; aU <= aUmax; aU += aUStep)
318         {
319           P1 = aS->Value(aU, aVmin);
320           P2 = aS->Value(aU, aVmax);
321           if (P1.SquareDistance(P2) > aTol2)
322           {
323             isVPeriodic = Standard_False;
324             break;
325           }
326         }
327       }
328       // 2. Verify periodicity of surface inside UV-bounds of the edge
329       if (isVPeriodic) // the flag still not changed
330       {
331         Standard_Real aU = (aUmin + aUmax) * 0.5;
332         Standard_Real aV[6]; // values of V lying out of surface boundaries
333         Standard_Real aVpp[6]; // corresponding V-values plus/minus period
334         Standard_Integer aNbPnt = 0;
335         if (aYmin < aVmin)
336         {
337           aV[0] = aYmin;
338           aV[1] = (aYmin + aVmin) * 0.5;
339           aV[2] = aVmin;
340           aVpp[0] = aV[0] + aVmax - aVmin;
341           aVpp[1] = aV[1] + aVmax - aVmin;
342           aVpp[2] = aV[2] + aVmax - aVmin;
343           aNbPnt += 3;
344         }
345         if (aYmax > aVmax)
346         {
347           aV[aNbPnt]     = aVmax;
348           aV[aNbPnt + 1] = (aYmax + aVmax) * 0.5;
349           aV[aNbPnt + 2] = aYmax;
350           aVpp[aNbPnt]     = aV[aNbPnt] - aVmax + aVmin;
351           aVpp[aNbPnt + 1] = aV[aNbPnt + 1] - aVmax + aVmin;
352           aVpp[aNbPnt + 2] = aV[aNbPnt + 2] - aVmax + aVmin;
353           aNbPnt += 3;
354         }
355         for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
356         {
357           P1 = aS->Value(aU, aV[anInd]);
358           P2 = aS->Value(aU, aVpp[anInd]);
359           if (P1.SquareDistance(P2) > aTol2)
360           {
361             isVPeriodic = Standard_False;
362             break;
363           }
364         }
365       }
366     }
367
368     if (!isVPeriodic)
369     {
370       if((aYmin<aVmin) && (aVmin < aYmax))
371       {
372         aYmin=aVmin;
373       }
374       if((aYmin < aVmax) && (aVmax < aYmax))
375       {
376         aYmax=aVmax;
377       }
378     }
379   }
380   
381   aBoxS.Update(aXmin, aYmin, aXmax, aYmax);
382   
383   aB.Add(aBoxS);
384 }
385
386 //=======================================================================
387 //function : Update
388 //purpose  : 
389 //=======================================================================
390
391 void BRepTools::Update(const TopoDS_Vertex&)
392 {
393 }
394
395 //=======================================================================
396 //function : Update
397 //purpose  : 
398 //=======================================================================
399
400 void BRepTools::Update(const TopoDS_Edge&)
401 {
402 }
403
404 //=======================================================================
405 //function : Update
406 //purpose  : 
407 //=======================================================================
408
409 void BRepTools::Update(const TopoDS_Wire&)
410 {
411 }
412
413 //=======================================================================
414 //function : Update
415 //purpose  : 
416 //=======================================================================
417
418 void BRepTools::Update(const TopoDS_Face& F)
419 {
420   if (!F.Checked()) {
421     UpdateFaceUVPoints(F);
422     F.TShape()->Checked(Standard_True);
423   }
424 }
425
426 //=======================================================================
427 //function : Update
428 //purpose  : 
429 //=======================================================================
430
431 void BRepTools::Update(const TopoDS_Shell& S)
432 {
433   TopExp_Explorer ex(S,TopAbs_FACE);
434   while (ex.More()) {
435     Update(TopoDS::Face(ex.Current()));
436     ex.Next();
437   }
438 }
439
440 //=======================================================================
441 //function : Update
442 //purpose  : 
443 //=======================================================================
444
445 void BRepTools::Update(const TopoDS_Solid& S)
446 {
447   TopExp_Explorer ex(S,TopAbs_FACE);
448   while (ex.More()) {
449     Update(TopoDS::Face(ex.Current()));
450     ex.Next();
451   }
452 }
453
454 //=======================================================================
455 //function : Update
456 //purpose  : 
457 //=======================================================================
458
459 void BRepTools::Update(const TopoDS_CompSolid& CS)
460 {
461   TopExp_Explorer ex(CS,TopAbs_FACE);
462   while (ex.More()) {
463     Update(TopoDS::Face(ex.Current()));
464     ex.Next();
465   }
466 }
467
468 //=======================================================================
469 //function : Update
470 //purpose  : 
471 //=======================================================================
472
473 void BRepTools::Update(const TopoDS_Compound& C)
474 {
475   TopExp_Explorer ex(C,TopAbs_FACE);
476   while (ex.More()) {
477     Update(TopoDS::Face(ex.Current()));
478     ex.Next();
479   }
480 }
481
482 //=======================================================================
483 //function : Update
484 //purpose  : 
485 //=======================================================================
486
487 void BRepTools::Update(const TopoDS_Shape& S)
488 {
489   switch (S.ShapeType()) {
490
491   case TopAbs_VERTEX :
492     Update(TopoDS::Vertex(S));
493     break;
494
495   case TopAbs_EDGE :
496     Update(TopoDS::Edge(S));
497     break;
498
499   case TopAbs_WIRE :
500     Update(TopoDS::Wire(S));
501     break;
502
503   case TopAbs_FACE :
504     Update(TopoDS::Face(S));
505     break;
506
507   case TopAbs_SHELL :
508     Update(TopoDS::Shell(S));
509     break;
510
511   case TopAbs_SOLID :
512     Update(TopoDS::Solid(S));
513     break;
514
515   case TopAbs_COMPSOLID :
516     Update(TopoDS::CompSolid(S));
517     break;
518
519   case TopAbs_COMPOUND :
520     Update(TopoDS::Compound(S));
521     break;
522
523   default:
524     break;
525
526   }
527 }
528
529
530 //=======================================================================
531 //function : UpdateFaceUVPoints
532 //purpose  : reset the UV points of a  Face
533 //=======================================================================
534
535 void  BRepTools::UpdateFaceUVPoints(const TopoDS_Face& F)
536 {
537   // Recompute for each edge the two UV points in order to have the same
538   // UV point on connected edges.
539
540   // First edge loop, store the vertices in a Map with their 2d points
541
542   BRepTools_MapOfVertexPnt2d theVertices;
543   TopoDS_Iterator expE,expV;
544   TopoDS_Iterator EdgeIt,VertIt;
545   TColStd_SequenceOfReal aFSeq, aLSeq;
546   TColGeom2d_SequenceOfCurve aCSeq;
547   TopTools_SequenceOfShape aShSeq;
548   gp_Pnt2d P;
549   Standard_Integer i;
550   // a 3d tolerance for UV !!
551   Standard_Real tolerance = BRep_Tool::Tolerance(F);
552   TColgp_SequenceOfPnt2d emptySequence;
553   
554   for (expE.Initialize(F); expE.More(); expE.Next()) {
555     if(expE.Value().ShapeType() != TopAbs_WIRE)
556       continue;
557     
558     EdgeIt.Initialize(expE.Value());
559     for( ; EdgeIt.More(); EdgeIt.Next())
560     {
561       const TopoDS_Edge& E = TopoDS::Edge(EdgeIt.Value());
562       Standard_Real f,l;
563       Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l);
564
565       aFSeq.Append(f);
566       aLSeq.Append(l);
567       aCSeq.Append(C);
568       aShSeq.Append(E);
569
570       if (C.IsNull()) continue;
571
572       for (expV.Initialize(E.Oriented(TopAbs_FORWARD)); 
573            expV.More(); expV.Next()) {
574         
575         const TopoDS_Vertex& V = TopoDS::Vertex(expV.Value());
576         
577         TopAbs_Orientation Vori = V.Orientation();
578         if ( Vori == TopAbs_INTERNAL ) {
579           continue;
580         }
581         
582         Standard_Real p = BRep_Tool::Parameter(V,E,F);
583         C->D0(p,P);
584         if (!theVertices.IsBound(V)) 
585           theVertices.Bind(V,emptySequence);
586         TColgp_SequenceOfPnt2d& S = theVertices(V);
587         for (i = 1; i <= S.Length(); i++) {
588           if (P.Distance(S(i)) < tolerance) break;
589         }
590         if (i > S.Length())
591           S.Append(P);
592       }
593     }
594   }
595  
596   // second edge loop, update the edges 2d points
597   TopoDS_Vertex Vf,Vl;
598   gp_Pnt2d Pf,Pl;
599
600   for(Standard_Integer j = 1; j <= aShSeq.Length(); j++)
601   {
602     const TopoDS_Edge& E = TopoDS::Edge(aShSeq.Value(j));
603     const Handle(Geom2d_Curve)& C = aCSeq.Value(j);
604     if (C.IsNull()) continue;
605     
606     TopExp::Vertices(E,Vf,Vl);
607     if (Vf.IsNull()) {
608       Pf.SetCoord(RealLast(),RealLast());
609     }
610     else {
611       if ( Vf.Orientation() == TopAbs_INTERNAL ) {
612         continue;
613       }
614       const TColgp_SequenceOfPnt2d& seqf = theVertices(Vf);
615       if (seqf.Length() == 1) 
616         Pf = seqf(1);
617       else {
618         C->D0(aFSeq.Value(j),Pf);
619         for (i = 1; i <= seqf.Length(); i++) {
620           if (Pf.Distance(seqf(i)) <= tolerance) {
621             Pf = seqf(i);
622             break;
623           }
624         }
625       }
626     }
627     if (Vl.IsNull()) {
628       Pl.SetCoord(RealLast(),RealLast());
629     }
630     else {
631       if ( Vl.Orientation() == TopAbs_INTERNAL ) {
632         continue;
633       }
634       const TColgp_SequenceOfPnt2d& seql = theVertices(Vl);
635       if (seql.Length() == 1) 
636         Pl = seql(1);
637       else {
638         C->D0(aLSeq.Value(j),Pl);
639         for (i = 1; i <= seql.Length(); i++) {
640           if (Pl.Distance(seql(i)) <= tolerance) {
641             Pl = seql(i);
642             break;
643           }
644         }
645       }
646     }
647
648     // set the correct points
649     BRep_Tool::SetUVPoints(E,F,Pf,Pl);
650   }
651 }
652
653
654
655 //=======================================================================
656 //function : Compare
657 //purpose  : 
658 //=======================================================================
659
660 Standard_Boolean BRepTools::Compare(const TopoDS_Vertex& V1,
661                                     const TopoDS_Vertex& V2)
662 {
663   if (V1.IsSame(V2)) return Standard_True;
664   gp_Pnt p1 = BRep_Tool::Pnt(V1);
665   gp_Pnt p2 = BRep_Tool::Pnt(V2);
666   Standard_Real l = p1.Distance(p2);
667   if (l <= BRep_Tool::Tolerance(V1)) return Standard_True;
668   if (l <= BRep_Tool::Tolerance(V2)) return Standard_True;
669   return Standard_False;
670 }
671
672 //=======================================================================
673 //function : Compare
674 //purpose  : 
675 //=======================================================================
676
677 Standard_Boolean BRepTools::Compare(const TopoDS_Edge& E1,
678                                     const TopoDS_Edge& E2)
679 {
680   if (E1.IsSame(E2)) return Standard_True;
681   return Standard_False;
682 }
683
684 //=======================================================================
685 //function : OuterWire
686 //purpose  : 
687 //=======================================================================
688
689 TopoDS_Wire  BRepTools::OuterWire(const TopoDS_Face& F)
690 {
691   TopoDS_Wire Wres;
692   TopExp_Explorer expw (F,TopAbs_WIRE);
693
694   if (expw.More()) {
695     Wres = TopoDS::Wire(expw.Current());
696     expw.Next();
697     if (expw.More()) {
698       Standard_Real UMin, UMax, VMin, VMax;
699       Standard_Real umin, umax, vmin, vmax;
700       BRepTools::UVBounds(F,Wres,UMin,UMax,VMin,VMax);
701         while (expw.More()) {
702           const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
703           BRepTools::UVBounds(F,W,umin, umax, vmin, vmax);
704           if ((umin <= UMin) &&
705               (umax >= UMax) &&
706               (vmin <= VMin) &&
707               (vmax >= VMax)) {
708             Wres = W;
709             UMin = umin;
710             UMax = umax;
711             VMin = vmin;
712             VMax = vmax;
713           }
714           expw.Next();
715         }
716     }
717   }
718   return Wres;
719 }
720
721 //=======================================================================
722 //function : Map3DEdges
723 //purpose  : 
724 //=======================================================================
725
726 void  BRepTools::Map3DEdges(const TopoDS_Shape& S, 
727                             TopTools_IndexedMapOfShape& M)
728 {
729   TopExp_Explorer Ex;
730   for (Ex.Init(S,TopAbs_EDGE); Ex.More(); Ex.Next()) {
731     if (!BRep_Tool::Degenerated(TopoDS::Edge(Ex.Current())))
732       M.Add(Ex.Current());
733   }
734 }
735
736 //=======================================================================
737 //function : Dump
738 //purpose  : 
739 //=======================================================================
740
741 void  BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
742 {
743   BRepTools_ShapeSet SS;
744   SS.Add(Sh);
745   SS.Dump(Sh,S);
746   SS.Dump(S);
747 }
748
749 //=======================================================================
750 //function : Write
751 //purpose  : 
752 //=======================================================================
753
754 void  BRepTools::Write(const TopoDS_Shape& Sh, Standard_OStream& S,
755                        const Handle(Message_ProgressIndicator)& PR)
756 {
757   BRepTools_ShapeSet SS;
758   SS.SetProgress(PR);
759   SS.Add(Sh);
760   SS.Write(S);
761   SS.Write(Sh,S);
762 }
763
764
765 //=======================================================================
766 //function : Read
767 //purpose  : 
768 //=======================================================================
769
770 void  BRepTools::Read(TopoDS_Shape& Sh, 
771                       istream& S, 
772                       const BRep_Builder& B,
773                       const Handle(Message_ProgressIndicator)& PR)
774 {
775   BRepTools_ShapeSet SS(B);
776   SS.SetProgress(PR);
777   SS.Read(S);
778   SS.Read(Sh,S);
779 }
780
781 //=======================================================================
782 //function : Write
783 //purpose  : 
784 //=======================================================================
785
786 Standard_Boolean  BRepTools::Write(const TopoDS_Shape& Sh, 
787                                    const Standard_CString File,
788                                    const Handle(Message_ProgressIndicator)& PR)
789 {
790   ofstream os;
791   OSD_OpenStream(os, File, ios::out);
792   if (!os.rdbuf()->is_open()) return Standard_False;
793
794   Standard_Boolean isGood = (os.good() && !os.eof());
795   if(!isGood)
796     return isGood;
797   
798   BRepTools_ShapeSet SS;
799   SS.SetProgress(PR);
800   SS.Add(Sh);
801   
802   os << "DBRep_DrawableShape\n";  // for easy Draw read
803   SS.Write(os);
804   isGood = os.good();
805   if(isGood )
806     SS.Write(Sh,os);
807   os.flush();
808   isGood = os.good();
809
810   errno = 0;
811   os.close();
812   isGood = os.good() && isGood && !errno;
813
814   return isGood;
815 }
816
817 //=======================================================================
818 //function : Read
819 //purpose  : 
820 //=======================================================================
821
822 Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh, 
823                                  const Standard_CString File,
824                                  const BRep_Builder& B,
825                                  const Handle(Message_ProgressIndicator)& PR)
826 {
827   filebuf fic;
828   istream in(&fic);
829   OSD_OpenFileBuf(fic,File,ios::in);
830   if(!fic.is_open()) return Standard_False;
831   
832   BRepTools_ShapeSet SS(B);
833   SS.SetProgress(PR);
834   SS.Read(in);
835   if(!SS.NbShapes()) return Standard_False;
836   SS.Read(Sh,in);
837   return Standard_True;
838 }
839
840
841 //=======================================================================
842 //function : Clean
843 //purpose  : 
844 //=======================================================================
845
846 void BRepTools::Clean(const TopoDS_Shape& theShape)
847 {
848   BRep_Builder aBuilder;
849   Handle(Poly_Triangulation) aNullTriangulation;
850   Handle(Poly_PolygonOnTriangulation) aNullPoly;
851
852   if (theShape.IsNull())
853     return;
854
855   TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
856   for (; aFaceIt.More(); aFaceIt.Next())
857   {
858     const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
859
860     TopLoc_Location aLoc;
861     const Handle(Poly_Triangulation)& aTriangulation =
862       BRep_Tool::Triangulation(aFace, aLoc);
863
864     if (aTriangulation.IsNull())
865       continue;
866
867     // Nullify edges
868     TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE);
869     for (; aEdgeIt.More(); aEdgeIt.Next())
870     {
871       const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
872       aBuilder.UpdateEdge(aEdge, aNullPoly, aTriangulation, aLoc);
873     }
874
875     aBuilder.UpdateFace(aFace, aNullTriangulation);
876   }
877 }
878
879 //=======================================================================
880 //function : RemoveUnusedPCurves
881 //purpose  : 
882 //=======================================================================
883
884 void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S)
885 {
886   TColStd_MapOfTransient UsedSurfaces;
887   
888   TopExp_Explorer Explo(S, TopAbs_FACE);
889   for (; Explo.More(); Explo.Next())
890   {
891     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
892     TopLoc_Location aLoc;
893     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
894     UsedSurfaces.Add(aSurf);
895   }
896
897   TopTools_IndexedMapOfShape Emap;
898   TopExp::MapShapes(S, TopAbs_EDGE, Emap);
899
900   Standard_Integer i;
901   for (i = 1; i <= Emap.Extent(); i++)
902   {
903     const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape());
904     BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves();
905     BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr );
906     while (itrep.More())
907     {
908       Standard_Boolean ToRemove = Standard_False;
909       
910       Handle(BRep_CurveRepresentation) CurveRep = itrep.Value();
911       if (CurveRep->IsCurveOnSurface())
912       {
913         Handle(Geom_Surface) aSurface = CurveRep->Surface();
914         if (!UsedSurfaces.Contains(aSurface))
915           ToRemove = Standard_True;
916       }
917       else if (CurveRep->IsRegularity())
918       {
919         Handle(Geom_Surface) Surf1 = CurveRep->Surface();
920         Handle(Geom_Surface) Surf2 = CurveRep->Surface2();
921         ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2));
922       }
923       
924       if (ToRemove)
925         lcr.Remove(itrep);
926       else
927         itrep.Next();
928     }
929   }
930 }
931
932 //=======================================================================
933 //function : Triangulation
934 //purpose  : 
935 //=======================================================================
936
937 Standard_Boolean  BRepTools::Triangulation(const TopoDS_Shape&    S,
938                                            const Standard_Real    deflec)
939 {
940   TopExp_Explorer exf, exe;
941   TopLoc_Location l;
942   Handle(Poly_Triangulation) T;
943   Handle(Poly_PolygonOnTriangulation) Poly;
944
945   for (exf.Init(S, TopAbs_FACE); exf.More(); exf.Next()) {
946     const TopoDS_Face& F = TopoDS::Face(exf.Current());
947     T = BRep_Tool::Triangulation(F, l);
948     if (T.IsNull() || (T->Deflection() > deflec))
949       return Standard_False;
950     for (exe.Init(F, TopAbs_EDGE); exe.More(); exe.Next()) {
951       const TopoDS_Edge& E = TopoDS::Edge(exe.Current());
952       Poly = BRep_Tool::PolygonOnTriangulation(E, T, l);
953       if (Poly.IsNull()) return Standard_False;
954     }
955   }
956   return Standard_True;
957 }
958
959
960 //=======================================================================
961 //function : IsReallyClosed
962 //purpose  : 
963 //=======================================================================
964
965 Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
966                                            const TopoDS_Face& F)
967 {
968   if (!BRep_Tool::IsClosed(E,F)) {
969     return Standard_False;
970   }
971   Standard_Integer nbocc = 0;
972   TopExp_Explorer exp;
973   for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) {
974     if (exp.Current().IsSame(E)) {
975       nbocc++;
976     }
977   }
978   return nbocc == 2;
979 }
980
981 //=======================================================================
982 //function : EvalAndUpdateTol
983 //purpose  : 
984 //=======================================================================
985
986 Standard_Real BRepTools::EvalAndUpdateTol(const TopoDS_Edge& theE, 
987                                  const Handle(Geom_Curve)& C3d, 
988                                  const Handle(Geom2d_Curve) C2d, 
989                                  const Handle(Geom_Surface)& S,
990                                  const Standard_Real f,
991                                  const Standard_Real l)
992 {
993   Standard_Real newtol = 0.;
994   Standard_Real first = f, last = l;
995   //Set first, last to avoid ErrosStatus = 2 because of 
996   //too strong checking of limits in class CheckCurveOnSurface
997   //
998   if(!C3d->IsPeriodic())
999   {
1000     first = Max(first, C3d->FirstParameter());
1001     last = Min(last, C3d->LastParameter());
1002   }
1003   if(!C2d->IsPeriodic())
1004   {
1005     first = Max(first, C2d->FirstParameter());
1006     last = Min(last, C2d->LastParameter());
1007   }
1008
1009   GeomLib_CheckCurveOnSurface CT(C3d, S, first, last);
1010   CT.Perform(C2d);
1011   if(CT.IsDone())
1012   {
1013     newtol = CT.MaxDistance();
1014   }
1015   else
1016   {
1017     if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 &&
1018       (C3d->IsPeriodic() || C2d->IsPeriodic())))
1019     {
1020       //Try to estimate by sample points
1021       Standard_Integer nbint = 22;
1022       Standard_Real dt = (last - first) / nbint;
1023       dt = Max(dt, Precision::Confusion());
1024       Standard_Real d, dmax = 0.;
1025       gp_Pnt2d aP2d;
1026       gp_Pnt aPC, aPS;
1027       Standard_Integer cnt = 0; 
1028       Standard_Real t = first;
1029       for(; t <= last; t += dt)
1030       {
1031         cnt++;
1032         C2d->D0(t, aP2d);
1033         C3d->D0(t, aPC);
1034         S->D0(aP2d.X(), aP2d.Y(), aPS);
1035         d = aPS.SquareDistance(aPC);
1036         if(d > dmax)
1037         {
1038           dmax = d;
1039         }
1040       }
1041       if(cnt < nbint + 1)
1042       {
1043         t = last;
1044         C2d->D0(t, aP2d);
1045         C3d->D0(t, aPC);
1046         S->D0(aP2d.X(), aP2d.Y(), aPS);
1047         d = aPS.SquareDistance(aPC);
1048         if(d > dmax)
1049         {
1050           dmax = d;
1051         }
1052       }
1053
1054       newtol = 1.2 * Sqrt(dmax);
1055     }
1056   }
1057   Standard_Real Tol = BRep_Tool::Tolerance(theE);
1058   if(newtol > Tol)
1059   {
1060     Tol = newtol;
1061     BRep_Builder B;
1062     B.UpdateEdge(theE, Tol);
1063   }
1064
1065   return Tol;
1066
1067 }
1068
1069