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