0029081: With Mingw-w64 Unicode Paths Do Not Work
[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.is_open() || !os.good())
793     return Standard_False;
794
795   Standard_Boolean isGood = (os.good() && !os.eof());
796   if(!isGood)
797     return isGood;
798   
799   BRepTools_ShapeSet SS;
800   SS.SetProgress(PR);
801   SS.Add(Sh);
802   
803   os << "DBRep_DrawableShape\n";  // for easy Draw read
804   SS.Write(os);
805   isGood = os.good();
806   if(isGood )
807     SS.Write(Sh,os);
808   os.flush();
809   isGood = os.good();
810
811   errno = 0;
812   os.close();
813   isGood = os.good() && isGood && !errno;
814
815   return isGood;
816 }
817
818 //=======================================================================
819 //function : Read
820 //purpose  : 
821 //=======================================================================
822
823 Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh, 
824                                  const Standard_CString File,
825                                  const BRep_Builder& B,
826                                  const Handle(Message_ProgressIndicator)& PR)
827 {
828   filebuf fic;
829   istream in(&fic);
830   OSD_OpenStream (fic, File, ios::in);
831   if(!fic.is_open()) return Standard_False;
832   
833   BRepTools_ShapeSet SS(B);
834   SS.SetProgress(PR);
835   SS.Read(in);
836   if(!SS.NbShapes()) return Standard_False;
837   SS.Read(Sh,in);
838   return Standard_True;
839 }
840
841
842 //=======================================================================
843 //function : Clean
844 //purpose  : 
845 //=======================================================================
846
847 void BRepTools::Clean(const TopoDS_Shape& theShape)
848 {
849   BRep_Builder aBuilder;
850   Handle(Poly_Triangulation) aNullTriangulation;
851   Handle(Poly_PolygonOnTriangulation) aNullPoly;
852
853   if (theShape.IsNull())
854     return;
855
856   TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
857   for (; aFaceIt.More(); aFaceIt.Next())
858   {
859     const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
860
861     TopLoc_Location aLoc;
862     const Handle(Poly_Triangulation)& aTriangulation =
863       BRep_Tool::Triangulation(aFace, aLoc);
864
865     if (aTriangulation.IsNull())
866       continue;
867
868     // Nullify edges
869     TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE);
870     for (; aEdgeIt.More(); aEdgeIt.Next())
871     {
872       const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
873       aBuilder.UpdateEdge(aEdge, aNullPoly, aTriangulation, aLoc);
874     }
875
876     aBuilder.UpdateFace(aFace, aNullTriangulation);
877   }
878
879   // Iterate over all edges seeking for 3d polygons
880   Handle (Poly_Polygon3D) aNullPoly3d;
881   TopExp_Explorer aEdgeIt (theShape, TopAbs_EDGE);
882   for (; aEdgeIt.More (); aEdgeIt.Next ())
883   {
884     const TopoDS_Edge& aEdge = TopoDS::Edge (aEdgeIt.Current ());
885
886     TopLoc_Location aLoc;
887     Handle (Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D (aEdge, aLoc);
888     if (aPoly3d.IsNull ())
889       continue;
890
891     aBuilder.UpdateEdge (aEdge, aNullPoly3d);  
892   }
893 }
894
895 //=======================================================================
896 //function : RemoveUnusedPCurves
897 //purpose  : 
898 //=======================================================================
899
900 void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S)
901 {
902   TColStd_MapOfTransient UsedSurfaces;
903   
904   TopExp_Explorer Explo(S, TopAbs_FACE);
905   for (; Explo.More(); Explo.Next())
906   {
907     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
908     TopLoc_Location aLoc;
909     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
910     UsedSurfaces.Add(aSurf);
911   }
912
913   TopTools_IndexedMapOfShape Emap;
914   TopExp::MapShapes(S, TopAbs_EDGE, Emap);
915
916   Standard_Integer i;
917   for (i = 1; i <= Emap.Extent(); i++)
918   {
919     const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape());
920     BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves();
921     BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr );
922     while (itrep.More())
923     {
924       Standard_Boolean ToRemove = Standard_False;
925       
926       Handle(BRep_CurveRepresentation) CurveRep = itrep.Value();
927       if (CurveRep->IsCurveOnSurface())
928       {
929         Handle(Geom_Surface) aSurface = CurveRep->Surface();
930         if (!UsedSurfaces.Contains(aSurface))
931           ToRemove = Standard_True;
932       }
933       else if (CurveRep->IsRegularity())
934       {
935         Handle(Geom_Surface) Surf1 = CurveRep->Surface();
936         Handle(Geom_Surface) Surf2 = CurveRep->Surface2();
937         ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2));
938       }
939       
940       if (ToRemove)
941         lcr.Remove(itrep);
942       else
943         itrep.Next();
944     }
945   }
946 }
947
948 //=======================================================================
949 //function : Triangulation
950 //purpose  : 
951 //=======================================================================
952
953 Standard_Boolean  BRepTools::Triangulation(const TopoDS_Shape&    S,
954                                            const Standard_Real    deflec)
955 {
956   TopExp_Explorer exf, exe;
957   TopLoc_Location l;
958   Handle(Poly_Triangulation) T;
959   Handle(Poly_PolygonOnTriangulation) Poly;
960
961   for (exf.Init(S, TopAbs_FACE); exf.More(); exf.Next()) {
962     const TopoDS_Face& F = TopoDS::Face(exf.Current());
963     T = BRep_Tool::Triangulation(F, l);
964     if (T.IsNull() || (T->Deflection() > deflec))
965       return Standard_False;
966     for (exe.Init(F, TopAbs_EDGE); exe.More(); exe.Next()) {
967       const TopoDS_Edge& E = TopoDS::Edge(exe.Current());
968       Poly = BRep_Tool::PolygonOnTriangulation(E, T, l);
969       if (Poly.IsNull()) return Standard_False;
970     }
971   }
972   return Standard_True;
973 }
974
975
976 //=======================================================================
977 //function : IsReallyClosed
978 //purpose  : 
979 //=======================================================================
980
981 Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
982                                            const TopoDS_Face& F)
983 {
984   if (!BRep_Tool::IsClosed(E,F)) {
985     return Standard_False;
986   }
987   Standard_Integer nbocc = 0;
988   TopExp_Explorer exp;
989   for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) {
990     if (exp.Current().IsSame(E)) {
991       nbocc++;
992     }
993   }
994   return nbocc == 2;
995 }
996
997 //=======================================================================
998 //function : EvalAndUpdateTol
999 //purpose  : 
1000 //=======================================================================
1001
1002 Standard_Real BRepTools::EvalAndUpdateTol(const TopoDS_Edge& theE, 
1003                                  const Handle(Geom_Curve)& C3d, 
1004                                  const Handle(Geom2d_Curve) C2d, 
1005                                  const Handle(Geom_Surface)& S,
1006                                  const Standard_Real f,
1007                                  const Standard_Real l)
1008 {
1009   Standard_Real newtol = 0.;
1010   Standard_Real first = f, last = l;
1011   //Set first, last to avoid ErrosStatus = 2 because of 
1012   //too strong checking of limits in class CheckCurveOnSurface
1013   //
1014   if(!C3d->IsPeriodic())
1015   {
1016     first = Max(first, C3d->FirstParameter());
1017     last = Min(last, C3d->LastParameter());
1018   }
1019   if(!C2d->IsPeriodic())
1020   {
1021     first = Max(first, C2d->FirstParameter());
1022     last = Min(last, C2d->LastParameter());
1023   }
1024
1025   GeomLib_CheckCurveOnSurface CT(C3d, S, first, last);
1026   CT.Perform(C2d);
1027   if(CT.IsDone())
1028   {
1029     newtol = CT.MaxDistance();
1030   }
1031   else
1032   {
1033     if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 &&
1034       (C3d->IsPeriodic() || C2d->IsPeriodic())))
1035     {
1036       //Try to estimate by sample points
1037       Standard_Integer nbint = 22;
1038       Standard_Real dt = (last - first) / nbint;
1039       dt = Max(dt, Precision::Confusion());
1040       Standard_Real d, dmax = 0.;
1041       gp_Pnt2d aP2d;
1042       gp_Pnt aPC, aPS;
1043       Standard_Integer cnt = 0; 
1044       Standard_Real t = first;
1045       for(; t <= last; t += dt)
1046       {
1047         cnt++;
1048         C2d->D0(t, aP2d);
1049         C3d->D0(t, aPC);
1050         S->D0(aP2d.X(), aP2d.Y(), aPS);
1051         d = aPS.SquareDistance(aPC);
1052         if(d > dmax)
1053         {
1054           dmax = d;
1055         }
1056       }
1057       if(cnt < nbint + 1)
1058       {
1059         t = last;
1060         C2d->D0(t, aP2d);
1061         C3d->D0(t, aPC);
1062         S->D0(aP2d.X(), aP2d.Y(), aPS);
1063         d = aPS.SquareDistance(aPC);
1064         if(d > dmax)
1065         {
1066           dmax = d;
1067         }
1068       }
1069
1070       newtol = 1.2 * Sqrt(dmax);
1071     }
1072   }
1073   Standard_Real Tol = BRep_Tool::Tolerance(theE);
1074   if(newtol > Tol)
1075   {
1076     Tol = newtol;
1077     BRep_Builder B;
1078     B.UpdateEdge(theE, Tol);
1079   }
1080
1081   return Tol;
1082
1083 }
1084
1085