61e7a9035e8754c8ba1dd5515d4dbf77f77656c2
[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_GCurve.hxx>
23 #include <BRep_ListOfCurveRepresentation.hxx>
24 #include <BRep_TEdge.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepTools.hxx>
27 #include <BRepTools_MapOfVertexPnt2d.hxx>
28 #include <BRepTools_ShapeSet.hxx>
29 #include <BRepAdaptor_Surface.hxx>
30 #include <ElCLib.hxx>
31 #include <Geom2d_Curve.hxx>
32 #include <Geom2dAdaptor_Curve.hxx>
33 #include <Geom_BSplineSurface.hxx>
34 #include <Geom_Curve.hxx>
35 #include <Geom_RectangularTrimmedSurface.hxx>
36 #include <Geom_Surface.hxx>
37 #include <gp_Lin2d.hxx>
38 #include <gp_Vec2d.hxx>
39 #include <Message.hxx>
40 #include <OSD_FileSystem.hxx>
41 #include <OSD_OpenFile.hxx>
42 #include <Poly_PolygonOnTriangulation.hxx>
43 #include <Poly_Triangulation.hxx>
44 #include <Precision.hxx>
45 #include <Standard_ErrorHandler.hxx>
46 #include <Standard_Failure.hxx>
47 #include <Standard_Stream.hxx>
48 #include <TColGeom2d_SequenceOfCurve.hxx>
49 #include <TColgp_SequenceOfPnt2d.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TColStd_HArray1OfInteger.hxx>
52 #include <TColStd_MapOfTransient.hxx>
53 #include <TColStd_SequenceOfReal.hxx>
54 #include <TopExp.hxx>
55 #include <TopExp_Explorer.hxx>
56 #include <TopoDS.hxx>
57 #include <TopoDS_Compound.hxx>
58 #include <TopoDS_CompSolid.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Face.hxx>
61 #include <TopoDS_Shape.hxx>
62 #include <TopoDS_Shell.hxx>
63 #include <TopoDS_Solid.hxx>
64 #include <TopoDS_Vertex.hxx>
65 #include <TopoDS_Wire.hxx>
66 #include <TopTools_SequenceOfShape.hxx>
67 #include <GeomLib_CheckCurveOnSurface.hxx>
68 #include <errno.h>
69
70
71 //=======================================================================
72 //function : UVBounds
73 //purpose  : 
74 //=======================================================================
75 void  BRepTools::UVBounds(const TopoDS_Face& F, 
76                           Standard_Real& UMin, Standard_Real& UMax, 
77                           Standard_Real& VMin, Standard_Real& VMax)
78 {
79   Bnd_Box2d B;
80   AddUVBounds(F,B);
81   if (!B.IsVoid())
82   {
83     B.Get(UMin,VMin,UMax,VMax);
84   }
85   else
86   {
87     UMin = UMax = VMin = VMax = 0.0;
88   }
89 }
90
91 //=======================================================================
92 //function : UVBounds
93 //purpose  : 
94 //=======================================================================
95
96 void  BRepTools::UVBounds(const TopoDS_Face& F,
97                           const TopoDS_Wire& W, 
98                           Standard_Real& UMin, Standard_Real& UMax, 
99                           Standard_Real& VMin, Standard_Real& VMax)
100 {
101   Bnd_Box2d B;
102   AddUVBounds(F,W,B);
103   if (!B.IsVoid())
104   {
105     B.Get(UMin,VMin,UMax,VMax);
106   }
107   else
108   {
109     UMin = UMax = VMin = VMax = 0.0;
110   }
111 }
112
113
114 //=======================================================================
115 //function : UVBounds
116 //purpose  : 
117 //=======================================================================
118
119 void  BRepTools::UVBounds(const TopoDS_Face& F,
120                           const TopoDS_Edge& E, 
121                           Standard_Real& UMin, Standard_Real& UMax, 
122                           Standard_Real& VMin, Standard_Real& VMax)
123 {
124   Bnd_Box2d B;
125   AddUVBounds(F,E,B);
126   if (!B.IsVoid())
127   {
128     B.Get(UMin,VMin,UMax,VMax);
129   }
130   else
131   {
132     UMin = UMax = VMin = VMax = 0.0;
133   }
134 }
135
136 //=======================================================================
137 //function : AddUVBounds
138 //purpose  : 
139 //=======================================================================
140
141 void  BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B)
142 {
143   TopoDS_Face F = FF;
144   F.Orientation(TopAbs_FORWARD);
145   TopExp_Explorer ex(F,TopAbs_EDGE);
146
147   // fill box for the given face
148   Bnd_Box2d aBox;
149   for (;ex.More();ex.Next()) {
150     BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),aBox);
151   }
152   
153   // if the box is empty (face without edges or without pcurves),
154   // get natural bounds
155   if (aBox.IsVoid()) {
156     Standard_Real UMin,UMax,VMin,VMax;
157     TopLoc_Location L;
158     const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, L);
159     if (aSurf.IsNull())
160     {
161       return;
162     }
163
164     aSurf->Bounds(UMin,UMax,VMin,VMax);
165     aBox.Update(UMin,VMin,UMax,VMax);
166   }
167   
168   // add face box to result
169   B.Add ( aBox );
170 }
171
172
173 //=======================================================================
174 //function : AddUVBounds
175 //purpose  : 
176 //=======================================================================
177 void  BRepTools::AddUVBounds(const TopoDS_Face& F, 
178                              const TopoDS_Wire& W, 
179                              Bnd_Box2d& B)
180 {
181   TopExp_Explorer ex;
182   for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) {
183     BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),B);
184     }
185 }
186
187
188 //=======================================================================
189 //function : AddUVBounds
190 //purpose  : 
191 //=======================================================================
192 void BRepTools::AddUVBounds(const TopoDS_Face& aF, 
193                             const TopoDS_Edge& aE,
194                             Bnd_Box2d& aB)
195 {
196   Standard_Real aT1, aT2, aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0;
197   Standard_Real aUmin, aUmax, aVmin, aVmax;
198   Bnd_Box2d aBoxC, aBoxS; 
199   TopLoc_Location aLoc;
200   //
201   const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
202   if (aC2D.IsNull()) {
203     return;
204   }
205   //
206   BndLib_Add2dCurve::Add(aC2D, aT1, aT2, 0., aBoxC);
207   if (!aBoxC.IsVoid())
208   {
209     aBoxC.Get(aXmin, aYmin, aXmax, aYmax);
210   }
211   //
212   Handle(Geom_Surface) aS = BRep_Tool::Surface(aF, aLoc);
213   aS->Bounds(aUmin, aUmax, aVmin, aVmax);
214
215   if(aS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
216   {
217     const Handle(Geom_RectangularTrimmedSurface) aSt = 
218                 Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
219     aS = aSt->BasisSurface();
220   }
221
222   //
223   if(!aS->IsUPeriodic())
224   {
225     Standard_Boolean isUPeriodic = Standard_False;
226
227     // Additional verification for U-periodicity for B-spline surfaces
228     // 1. Verify that the surface is U-closed (if such flag is false). Verification uses 2 points
229     // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points.
230     if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) &&
231         (aXmin < aUmin || aXmax > aUmax))
232     {
233       Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
234       isUPeriodic = Standard_True;
235       gp_Pnt P1, P2;
236       // 1. Verify that the surface is U-closed
237       if (!aS->IsUClosed())
238       {
239         Standard_Real aVStep = aVmax - aVmin;
240         for (Standard_Real aV = aVmin; aV <= aVmax; aV += aVStep)
241         {
242           P1 = aS->Value(aUmin, aV);
243           P2 = aS->Value(aUmax, aV);
244           if (P1.SquareDistance(P2) > aTol2)
245           {
246             isUPeriodic = Standard_False;
247             break;
248           }
249         }
250       }
251       // 2. Verify periodicity of surface inside UV-bounds of the edge
252       if (isUPeriodic) // the flag still not changed
253       {
254         Standard_Real aV = (aVmin + aVmax) * 0.5;
255         Standard_Real aU[6]; // values of U lying out of surface boundaries
256         Standard_Real aUpp[6]; // corresponding U-values plus/minus period
257         Standard_Integer aNbPnt = 0;
258         if (aXmin < aUmin)
259         {
260           aU[0] = aXmin;
261           aU[1] = (aXmin + aUmin) * 0.5;
262           aU[2] = aUmin;
263           aUpp[0] = aU[0] + aUmax - aUmin;
264           aUpp[1] = aU[1] + aUmax - aUmin;
265           aUpp[2] = aU[2] + aUmax - aUmin;
266           aNbPnt += 3;
267         }
268         if (aXmax > aUmax)
269         {
270           aU[aNbPnt]     = aUmax;
271           aU[aNbPnt + 1] = (aXmax + aUmax) * 0.5;
272           aU[aNbPnt + 2] = aXmax;
273           aUpp[aNbPnt]     = aU[aNbPnt] - aUmax + aUmin;
274           aUpp[aNbPnt + 1] = aU[aNbPnt + 1] - aUmax + aUmin;
275           aUpp[aNbPnt + 2] = aU[aNbPnt + 2] - aUmax + aUmin;
276           aNbPnt += 3;
277         }
278         for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
279         {
280           P1 = aS->Value(aU[anInd], aV);
281           P2 = aS->Value(aUpp[anInd], aV);
282           if (P1.SquareDistance(P2) > aTol2)
283           {
284             isUPeriodic = Standard_False;
285             break;
286           }
287         }
288       }
289     }
290
291     if (!isUPeriodic)
292     {
293       if((aXmin<aUmin) && (aUmin < aXmax))
294       {
295         aXmin=aUmin;
296       }
297       if((aXmin < aUmax) && (aUmax < aXmax))
298       {
299         aXmax=aUmax;
300       }
301     }
302   }
303
304   if(!aS->IsVPeriodic())
305   {
306     Standard_Boolean isVPeriodic = Standard_False;
307
308     // Additional verification for V-periodicity for B-spline surfaces
309     // 1. Verify that the surface is V-closed (if such flag is false). Verification uses 2 points
310     // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points.
311     if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) &&
312         (aYmin < aVmin || aYmax > aVmax))
313     {
314       Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
315       isVPeriodic = Standard_True;
316       gp_Pnt P1, P2;
317       // 1. Verify that the surface is V-closed
318       if (!aS->IsVClosed())
319       {
320         Standard_Real aUStep = aUmax - aUmin;
321         for (Standard_Real aU = aUmin; aU <= aUmax; aU += aUStep)
322         {
323           P1 = aS->Value(aU, aVmin);
324           P2 = aS->Value(aU, aVmax);
325           if (P1.SquareDistance(P2) > aTol2)
326           {
327             isVPeriodic = Standard_False;
328             break;
329           }
330         }
331       }
332       // 2. Verify periodicity of surface inside UV-bounds of the edge
333       if (isVPeriodic) // the flag still not changed
334       {
335         Standard_Real aU = (aUmin + aUmax) * 0.5;
336         Standard_Real aV[6]; // values of V lying out of surface boundaries
337         Standard_Real aVpp[6]; // corresponding V-values plus/minus period
338         Standard_Integer aNbPnt = 0;
339         if (aYmin < aVmin)
340         {
341           aV[0] = aYmin;
342           aV[1] = (aYmin + aVmin) * 0.5;
343           aV[2] = aVmin;
344           aVpp[0] = aV[0] + aVmax - aVmin;
345           aVpp[1] = aV[1] + aVmax - aVmin;
346           aVpp[2] = aV[2] + aVmax - aVmin;
347           aNbPnt += 3;
348         }
349         if (aYmax > aVmax)
350         {
351           aV[aNbPnt]     = aVmax;
352           aV[aNbPnt + 1] = (aYmax + aVmax) * 0.5;
353           aV[aNbPnt + 2] = aYmax;
354           aVpp[aNbPnt]     = aV[aNbPnt] - aVmax + aVmin;
355           aVpp[aNbPnt + 1] = aV[aNbPnt + 1] - aVmax + aVmin;
356           aVpp[aNbPnt + 2] = aV[aNbPnt + 2] - aVmax + aVmin;
357           aNbPnt += 3;
358         }
359         for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
360         {
361           P1 = aS->Value(aU, aV[anInd]);
362           P2 = aS->Value(aU, aVpp[anInd]);
363           if (P1.SquareDistance(P2) > aTol2)
364           {
365             isVPeriodic = Standard_False;
366             break;
367           }
368         }
369       }
370     }
371
372     if (!isVPeriodic)
373     {
374       if((aYmin<aVmin) && (aVmin < aYmax))
375       {
376         aYmin=aVmin;
377       }
378       if((aYmin < aVmax) && (aVmax < aYmax))
379       {
380         aYmax=aVmax;
381       }
382     }
383   }
384   
385   aBoxS.Update(aXmin, aYmin, aXmax, aYmax);
386   
387   aB.Add(aBoxS);
388 }
389
390 //=======================================================================
391 //function : Update
392 //purpose  : 
393 //=======================================================================
394
395 void BRepTools::Update(const TopoDS_Vertex&)
396 {
397 }
398
399 //=======================================================================
400 //function : Update
401 //purpose  : 
402 //=======================================================================
403
404 void BRepTools::Update(const TopoDS_Edge&)
405 {
406 }
407
408 //=======================================================================
409 //function : Update
410 //purpose  : 
411 //=======================================================================
412
413 void BRepTools::Update(const TopoDS_Wire&)
414 {
415 }
416
417 //=======================================================================
418 //function : Update
419 //purpose  : 
420 //=======================================================================
421
422 void BRepTools::Update(const TopoDS_Face& F)
423 {
424   if (!F.Checked()) {
425     UpdateFaceUVPoints(F);
426     F.TShape()->Checked(Standard_True);
427   }
428 }
429
430 //=======================================================================
431 //function : Update
432 //purpose  : 
433 //=======================================================================
434
435 void BRepTools::Update(const TopoDS_Shell& S)
436 {
437   TopExp_Explorer ex(S,TopAbs_FACE);
438   while (ex.More()) {
439     Update(TopoDS::Face(ex.Current()));
440     ex.Next();
441   }
442 }
443
444 //=======================================================================
445 //function : Update
446 //purpose  : 
447 //=======================================================================
448
449 void BRepTools::Update(const TopoDS_Solid& S)
450 {
451   TopExp_Explorer ex(S,TopAbs_FACE);
452   while (ex.More()) {
453     Update(TopoDS::Face(ex.Current()));
454     ex.Next();
455   }
456 }
457
458 //=======================================================================
459 //function : Update
460 //purpose  : 
461 //=======================================================================
462
463 void BRepTools::Update(const TopoDS_CompSolid& CS)
464 {
465   TopExp_Explorer ex(CS,TopAbs_FACE);
466   while (ex.More()) {
467     Update(TopoDS::Face(ex.Current()));
468     ex.Next();
469   }
470 }
471
472 //=======================================================================
473 //function : Update
474 //purpose  : 
475 //=======================================================================
476
477 void BRepTools::Update(const TopoDS_Compound& C)
478 {
479   TopExp_Explorer ex(C,TopAbs_FACE);
480   while (ex.More()) {
481     Update(TopoDS::Face(ex.Current()));
482     ex.Next();
483   }
484 }
485
486 //=======================================================================
487 //function : Update
488 //purpose  : 
489 //=======================================================================
490
491 void BRepTools::Update(const TopoDS_Shape& S)
492 {
493   switch (S.ShapeType()) {
494
495   case TopAbs_VERTEX :
496     Update(TopoDS::Vertex(S));
497     break;
498
499   case TopAbs_EDGE :
500     Update(TopoDS::Edge(S));
501     break;
502
503   case TopAbs_WIRE :
504     Update(TopoDS::Wire(S));
505     break;
506
507   case TopAbs_FACE :
508     Update(TopoDS::Face(S));
509     break;
510
511   case TopAbs_SHELL :
512     Update(TopoDS::Shell(S));
513     break;
514
515   case TopAbs_SOLID :
516     Update(TopoDS::Solid(S));
517     break;
518
519   case TopAbs_COMPSOLID :
520     Update(TopoDS::CompSolid(S));
521     break;
522
523   case TopAbs_COMPOUND :
524     Update(TopoDS::Compound(S));
525     break;
526
527   default:
528     break;
529
530   }
531 }
532
533 //=======================================================================
534 //function : UpdateFaceUVPoints
535 //purpose  : Reset the UV points of edges on the Face
536 //=======================================================================
537 void  BRepTools::UpdateFaceUVPoints(const TopoDS_Face& theF)
538 {
539   // For each edge of the face <F> reset the UV points to the bounding
540   // points of the parametric curve of the edge on the face.
541
542   // Get surface of the face
543   TopLoc_Location aLoc;
544   const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(theF, aLoc);
545   // Iterate on edges and reset UV points
546   TopExp_Explorer anExpE(theF, TopAbs_EDGE);
547   for (; anExpE.More(); anExpE.Next())
548   {
549     const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
550
551     const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
552     if (TE->Locked())
553       return;
554
555     const TopLoc_Location aELoc = aLoc.Predivided(aE.Location());
556     // Edge representations
557     BRep_ListOfCurveRepresentation& aLCR = TE->ChangeCurves();
558     BRep_ListIteratorOfListOfCurveRepresentation itLCR(aLCR);
559     for (; itLCR.More(); itLCR.Next())
560     {
561       Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itLCR.Value());
562       if (!GC.IsNull() && GC->IsCurveOnSurface(aSurf, aELoc))
563       {
564         // Update UV points
565         GC->Update();
566         break;
567       }
568     }
569   }
570 }
571
572 //=======================================================================
573 //function : Compare
574 //purpose  : 
575 //=======================================================================
576
577 Standard_Boolean BRepTools::Compare(const TopoDS_Vertex& V1,
578                                     const TopoDS_Vertex& V2)
579 {
580   if (V1.IsSame(V2)) return Standard_True;
581   gp_Pnt p1 = BRep_Tool::Pnt(V1);
582   gp_Pnt p2 = BRep_Tool::Pnt(V2);
583   Standard_Real l = p1.Distance(p2);
584   if (l <= BRep_Tool::Tolerance(V1)) return Standard_True;
585   if (l <= BRep_Tool::Tolerance(V2)) return Standard_True;
586   return Standard_False;
587 }
588
589 //=======================================================================
590 //function : Compare
591 //purpose  : 
592 //=======================================================================
593
594 Standard_Boolean BRepTools::Compare(const TopoDS_Edge& E1,
595                                     const TopoDS_Edge& E2)
596 {
597   if (E1.IsSame(E2)) return Standard_True;
598   return Standard_False;
599 }
600
601 //=======================================================================
602 //function : OuterWire
603 //purpose  : 
604 //=======================================================================
605
606 TopoDS_Wire  BRepTools::OuterWire(const TopoDS_Face& F)
607 {
608   TopoDS_Wire Wres;
609   TopExp_Explorer expw (F,TopAbs_WIRE);
610
611   if (expw.More()) {
612     Wres = TopoDS::Wire(expw.Current());
613     expw.Next();
614     if (expw.More()) {
615       Standard_Real UMin, UMax, VMin, VMax;
616       Standard_Real umin, umax, vmin, vmax;
617       BRepTools::UVBounds(F,Wres,UMin,UMax,VMin,VMax);
618         while (expw.More()) {
619           const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
620           BRepTools::UVBounds(F,W,umin, umax, vmin, vmax);
621           if (((umin - UMin) <= Precision::PConfusion()) &&
622               ((umax - UMax) >= -Precision::PConfusion()) &&
623               ((vmin - VMin) <= Precision::PConfusion()) &&
624               ((vmax - VMax) >= -Precision::PConfusion())) {
625             Wres = W;
626             UMin = umin;
627             UMax = umax;
628             VMin = vmin;
629             VMax = vmax;
630           }
631           expw.Next();
632         }
633     }
634   }
635   return Wres;
636 }
637
638 //=======================================================================
639 //function : Map3DEdges
640 //purpose  : 
641 //=======================================================================
642
643 void  BRepTools::Map3DEdges(const TopoDS_Shape& S, 
644                             TopTools_IndexedMapOfShape& M)
645 {
646   TopExp_Explorer Ex;
647   for (Ex.Init(S,TopAbs_EDGE); Ex.More(); Ex.Next()) {
648     if (!BRep_Tool::Degenerated(TopoDS::Edge(Ex.Current())))
649       M.Add(Ex.Current());
650   }
651 }
652
653 //=======================================================================
654 //function : Dump
655 //purpose  : 
656 //=======================================================================
657
658 void  BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
659 {
660   BRepTools_ShapeSet SS;
661   SS.Add(Sh);
662   SS.Dump(Sh,S);
663   SS.Dump(S);
664 }
665
666 //=======================================================================
667 //function : Write
668 //purpose  :
669 //=======================================================================
670 void BRepTools::Write (const TopoDS_Shape& theShape,
671                        Standard_OStream& theStream,
672                        const Standard_Boolean theWithTriangles,
673                        const Standard_Boolean theWithNormals,
674                        const TopTools_FormatVersion theVersion,
675                        const Message_ProgressRange& theProgress)
676 {
677   BRepTools_ShapeSet aShapeSet (theWithTriangles, theWithNormals);
678   aShapeSet.SetFormatNb (theVersion);
679   aShapeSet.Add (theShape);
680   aShapeSet.Write (theStream, theProgress);
681   aShapeSet.Write (theShape, theStream);
682 }
683
684 //=======================================================================
685 //function : Read
686 //purpose  : 
687 //=======================================================================
688
689 void  BRepTools::Read(TopoDS_Shape& Sh, 
690                       std::istream& S, 
691                       const BRep_Builder& B,
692                       const Message_ProgressRange& theProgress)
693 {
694   BRepTools_ShapeSet SS(B);
695   SS.Read(S, theProgress);
696   SS.Read(Sh,S);
697 }
698
699 //=======================================================================
700 //function : Write
701 //purpose  :
702 //=======================================================================
703 Standard_Boolean  BRepTools::Write (const TopoDS_Shape& theShape,
704                                     const Standard_CString theFile,
705                                     const Standard_Boolean theWithTriangles,
706                                     const Standard_Boolean theWithNormals,
707                                     const TopTools_FormatVersion theVersion,
708                                     const Message_ProgressRange& theProgress)
709 {
710   std::ofstream os;
711   OSD_OpenStream(os, theFile, std::ios::out);
712   if (!os.is_open() || !os.good())
713     return Standard_False;
714
715   Standard_Boolean isGood = (os.good() && !os.eof());
716   if(!isGood)
717     return isGood;
718
719   BRepTools_ShapeSet SS (theWithTriangles, theWithNormals);
720   SS.SetFormatNb (theVersion);
721   SS.Add (theShape);
722
723   os << "DBRep_DrawableShape\n";  // for easy Draw read
724   SS.Write(os, theProgress);
725   isGood = os.good();
726   if (isGood)
727   {
728     SS.Write (theShape, os);
729   }
730   os.flush();
731   isGood = os.good();
732
733   errno = 0;
734   os.close();
735   isGood = os.good() && isGood && !errno;
736
737   return isGood;
738 }
739
740 //=======================================================================
741 //function : Read
742 //purpose  : 
743 //=======================================================================
744
745 Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh, 
746                                  const Standard_CString File,
747                                  const BRep_Builder& B,
748                                  const Message_ProgressRange& theProgress)
749 {
750   std::filebuf fic;
751   std::istream in(&fic);
752   OSD_OpenStream (fic, File, std::ios::in);
753   if(!fic.is_open()) return Standard_False;
754   
755   BRepTools_ShapeSet SS(B);
756   SS.Read(in, theProgress);
757   if(!SS.NbShapes()) return Standard_False;
758   SS.Read(Sh,in);
759   return Standard_True;
760 }
761
762
763 //=======================================================================
764 //function : Clean
765 //purpose  : 
766 //=======================================================================
767
768 void BRepTools::Clean (const TopoDS_Shape& theShape, const Standard_Boolean theForce)
769 {
770   if (theShape.IsNull())
771     return;
772
773   BRep_Builder aBuilder;
774   Handle(Poly_Triangulation) aNullTriangulation;
775   Handle(Poly_PolygonOnTriangulation) aNullPoly;
776
777   TopTools_MapOfShape aShapeMap;
778   const TopLoc_Location anEmptyLoc;
779
780   TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
781   for (; aFaceIt.More(); aFaceIt.Next())
782   {
783     TopoDS_Shape aFaceNoLoc = aFaceIt.Value();
784     aFaceNoLoc.Location (anEmptyLoc);
785     if (!aShapeMap.Add (aFaceNoLoc))
786     {
787       // the face has already been processed
788       continue;
789     }
790
791     const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
792     if (!BRep_Tool::IsGeometric (aFace))
793     {
794       // Do not remove triangulation as there is no surface to recompute it.
795       continue;
796     }
797
798
799     TopLoc_Location aLoc;
800     const Handle(Poly_Triangulation)& aTriangulation =
801       BRep_Tool::Triangulation(aFace, aLoc);
802
803     if (aTriangulation.IsNull())
804       continue;
805
806     // Nullify edges
807     // Theoretically, the edges on the face (with surface) may have no geometry
808     // (no curve 3d or 2d or both). Such faces should be considered as invalid and
809     // are not supported by current implementation. So, both triangulation of the face
810     // and polygon on triangulation of the edges are removed unconditionally.
811     TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE);
812     for (; aEdgeIt.More(); aEdgeIt.Next())
813     {
814       const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current());
815       aBuilder.UpdateEdge(anEdge, aNullPoly, aTriangulation, aLoc);
816     }
817
818     aBuilder.UpdateFace(aFace, aNullTriangulation);
819   }
820
821   // Iterate over all edges seeking for 3d polygons
822   Handle (Poly_Polygon3D) aNullPoly3d;
823   TopExp_Explorer aEdgeIt (theShape, TopAbs_EDGE);
824   for (; aEdgeIt.More (); aEdgeIt.Next ())
825   {
826     TopoDS_Edge anEdge = TopoDS::Edge(aEdgeIt.Value()); 
827     anEdge.Location(anEmptyLoc);
828
829     if (!aShapeMap.Add(anEdge))
830     {
831       // the edge has already been processed
832       continue;
833     }
834
835     if (!BRep_Tool::IsGeometric(TopoDS::Edge(anEdge)))
836     {
837       // Do not remove polygon 3d as there is no curve to recompute it.
838       continue;
839     }
840
841     TopLoc_Location aLoc;
842     Handle(Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D(anEdge, aLoc);
843
844     if (!aPoly3d.IsNull())
845     {
846       aBuilder.UpdateEdge(anEdge, aNullPoly3d);
847     }
848     if (theForce)
849     {
850       Handle(BRep_CurveRepresentation) aCR;
851       BRep_TEdge* aTE = static_cast<BRep_TEdge*>(anEdge.TShape().get());
852       BRep_ListOfCurveRepresentation& aLCR = aTE->ChangeCurves();
853       BRep_ListIteratorOfListOfCurveRepresentation anIterCR(aLCR);
854
855       // find and remove all representations
856       while (anIterCR.More())
857       {
858         aCR = anIterCR.Value();
859         if (aCR->IsPolygonOnTriangulation())
860         {
861           aLCR.Remove(anIterCR);
862         }
863         else
864         {
865           anIterCR.Next();
866         }
867       }
868       aTE->Modified(Standard_True);
869     }
870   }
871 }
872 //=======================================================================
873 //function : CleanGeometry
874 //purpose  : 
875 //=======================================================================
876
877 void BRepTools::CleanGeometry(const TopoDS_Shape& theShape)
878 {
879   if (theShape.IsNull())
880     return;
881
882   BRep_Builder aBuilder;
883
884   for (TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
885   {
886     TopLoc_Location aLocation;
887     const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
888     const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(aFace, aLocation);
889
890     for (TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE); aEdgeIt.More(); aEdgeIt.Next())
891     {
892       const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current());
893       aBuilder.UpdateEdge(anEdge, Handle(Geom2d_Curve)(), aSurface,
894         aLocation, BRep_Tool::Tolerance(anEdge));
895     }
896
897     aBuilder.UpdateFace(aFace, Handle(Geom_Surface)(), aFace.Location(), BRep_Tool::Tolerance(aFace));
898   }
899
900   for (TopExp_Explorer aEdgeIt2(theShape, TopAbs_EDGE); aEdgeIt2.More(); aEdgeIt2.Next())
901   {
902     const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt2.Current());
903     aBuilder.UpdateEdge(anEdge, Handle(Geom_Curve)(),
904       TopLoc_Location(), BRep_Tool::Tolerance(anEdge));
905   }
906 }
907
908
909 //=======================================================================
910 //function : RemoveUnusedPCurves
911 //purpose  : 
912 //=======================================================================
913
914 void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S)
915 {
916   TColStd_MapOfTransient UsedSurfaces;
917   
918   TopExp_Explorer Explo(S, TopAbs_FACE);
919   for (; Explo.More(); Explo.Next())
920   {
921     TopoDS_Face aFace = TopoDS::Face(Explo.Current());
922     TopLoc_Location aLoc;
923     Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
924     UsedSurfaces.Add(aSurf);
925   }
926
927   TopTools_IndexedMapOfShape Emap;
928   TopExp::MapShapes(S, TopAbs_EDGE, Emap);
929
930   Standard_Integer i;
931   for (i = 1; i <= Emap.Extent(); i++)
932   {
933     const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape());
934     BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves();
935     BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr );
936     while (itrep.More())
937     {
938       Standard_Boolean ToRemove = Standard_False;
939       
940       Handle(BRep_CurveRepresentation) CurveRep = itrep.Value();
941       if (CurveRep->IsCurveOnSurface())
942       {
943         Handle(Geom_Surface) aSurface = CurveRep->Surface();
944         if (!UsedSurfaces.Contains(aSurface))
945           ToRemove = Standard_True;
946       }
947       else if (CurveRep->IsRegularity())
948       {
949         Handle(Geom_Surface) Surf1 = CurveRep->Surface();
950         Handle(Geom_Surface) Surf2 = CurveRep->Surface2();
951         ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2));
952       }
953       
954       if (ToRemove)
955         lcr.Remove(itrep);
956       else
957         itrep.Next();
958     }
959   }
960 }
961
962 //=======================================================================
963 //function : Triangulation
964 //purpose  : 
965 //=======================================================================
966
967 Standard_Boolean  BRepTools::Triangulation(const TopoDS_Shape& theShape,
968                                            const Standard_Real theLinDefl,
969                                            const Standard_Boolean theToCheckFreeEdges)
970 {
971   TopExp_Explorer anEdgeIter;
972   TopLoc_Location aDummyLoc;
973   for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
974   {
975     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
976     const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aDummyLoc);
977     if (aTri.IsNull()
978      || aTri->Deflection() > theLinDefl)
979     {
980       return Standard_False;
981     }
982
983     for (anEdgeIter.Init (aFace, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next())
984     {
985       const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current());
986       const Handle(Poly_PolygonOnTriangulation)& aPoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTri, aDummyLoc);
987       if (aPoly.IsNull())
988       {
989         return Standard_False;
990       }
991     }
992   }
993   if (!theToCheckFreeEdges)
994   {
995     return Standard_True;
996   }
997
998   Handle(Poly_Triangulation) anEdgeTri;
999   for (anEdgeIter.Init (theShape, TopAbs_EDGE, TopAbs_FACE); anEdgeIter.More(); anEdgeIter.Next())
1000   {
1001     const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current());
1002     const Handle(Poly_Polygon3D)& aPolygon = BRep_Tool::Polygon3D (anEdge, aDummyLoc);
1003     if (!aPolygon.IsNull())
1004     {
1005       if (aPolygon->Deflection() > theLinDefl)
1006       {
1007         return Standard_False;
1008       }
1009     }
1010     else
1011     {
1012       const Handle(Poly_PolygonOnTriangulation)& aPoly = BRep_Tool::PolygonOnTriangulation (anEdge, anEdgeTri, aDummyLoc);
1013       if (aPoly.IsNull()
1014        || anEdgeTri.IsNull()
1015        || anEdgeTri->Deflection() > theLinDefl)
1016       {
1017         return Standard_False;
1018       }
1019     }
1020   }
1021
1022   return Standard_True;
1023 }
1024
1025 //=======================================================================
1026 //function : LoadTriangulation
1027 //purpose  : 
1028 //=======================================================================
1029 Standard_Boolean BRepTools::LoadTriangulation (const TopoDS_Shape& theShape,
1030                                                const Standard_Integer theTriangulationIdx,
1031                                                const Standard_Boolean theToSetAsActive,
1032                                                const Handle(OSD_FileSystem)& theFileSystem)
1033 {
1034   Standard_ASSERT_RAISE (theTriangulationIdx >= -1, "Invalid negative triangulation index!");
1035
1036   Standard_Boolean wasLoaded = false;
1037   BRep_Builder aBuilder;
1038   TopLoc_Location aDummyLoc;
1039   const Handle(OSD_FileSystem)& aFileSystem = !theFileSystem.IsNull() ? theFileSystem : OSD_FileSystem::DefaultFileSystem();
1040   for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1041   {
1042     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1043     Handle(Poly_Triangulation) aTriangulation;
1044     if (theTriangulationIdx == -1)
1045     {
1046       // load an active triangulation
1047       aTriangulation = BRep_Tool::Triangulation (aFace, aDummyLoc);
1048     }
1049     else
1050     {
1051       const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc);
1052       if (theTriangulationIdx >= aTriangulations.Size())
1053       {
1054         // triangulation index is out of range
1055         continue;
1056       }
1057       Standard_Integer aTriangulationIdx = 0;
1058       for (Poly_ListOfTriangulation::Iterator anIter(aTriangulations);
1059            anIter.More(); anIter.Next(), aTriangulationIdx++)
1060       {
1061         if (aTriangulationIdx != theTriangulationIdx)
1062         {
1063           continue;
1064         }
1065         aTriangulation = anIter.Value();
1066         break;
1067       }
1068     }
1069     if (aTriangulation.IsNull() ||
1070        !aTriangulation->HasDeferredData())
1071     {
1072       // NULL triangulation, already loaded triangulation or triangulation without deferred storage
1073       // cannot be loaded
1074       continue;
1075     }
1076     if (aTriangulation->LoadDeferredData (aFileSystem))
1077     {
1078       wasLoaded = true;
1079       if (theToSetAsActive
1080        && (theTriangulationIdx != -1)) // triangulation is already active
1081       {
1082         aBuilder.UpdateFace (aFace, aTriangulation, false);
1083       }
1084     }
1085   }
1086   return wasLoaded;
1087 }
1088
1089 //=======================================================================
1090 //function : LoadAllTriangulation
1091 //purpose  : 
1092 //=======================================================================
1093 Standard_Boolean BRepTools::LoadAllTriangulations (const TopoDS_Shape& theShape,
1094                                                    const Handle(OSD_FileSystem)& theFileSystem)
1095 {
1096   Standard_Boolean wasLoaded = false;
1097   TopLoc_Location aDummyLoc;
1098   const Handle(OSD_FileSystem)& aFileSystem = !theFileSystem.IsNull() ? theFileSystem : OSD_FileSystem::DefaultFileSystem();
1099   for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1100   {
1101     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1102     for (Poly_ListOfTriangulation::Iterator anIter (BRep_Tool::Triangulations (aFace, aDummyLoc));
1103          anIter.More(); anIter.Next())
1104     {
1105       const Handle(Poly_Triangulation)& aTriangulation = anIter.Value();
1106       if (aTriangulation.IsNull() ||
1107          !aTriangulation->HasDeferredData())
1108       {
1109         // NULL triangulation, already loaded triangulation or triangulation without deferred storage
1110         // cannot be loaded
1111         continue;
1112       }
1113       wasLoaded = aTriangulation->LoadDeferredData (aFileSystem);
1114     }
1115   }
1116   return wasLoaded;
1117 }
1118
1119 //=======================================================================
1120 //function : UnloadTriangulation
1121 //purpose  : 
1122 //=======================================================================
1123 Standard_Boolean BRepTools::UnloadTriangulation (const TopoDS_Shape& theShape,
1124                                                  const Standard_Integer theTriangulationIdx)
1125 {
1126   Standard_ASSERT_RAISE (theTriangulationIdx >= -1, "Invalid negative triangulation index!");
1127
1128   Standard_Boolean wasUnloaded = false;
1129   TopLoc_Location aDummyLoc;
1130   for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1131   {
1132     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1133     Handle(Poly_Triangulation) aTriangulation;
1134     if (theTriangulationIdx == -1)
1135     {
1136       // unload an active triangulation
1137       aTriangulation = BRep_Tool::Triangulation (aFace, aDummyLoc);
1138     }
1139     else
1140     {
1141       Standard_Integer aTriangulationIdx = 0;
1142       const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc);
1143       if (theTriangulationIdx >= aTriangulations.Size())
1144       {
1145         // triangulation index is out of range
1146         continue;
1147       }
1148       for (Poly_ListOfTriangulation::Iterator anIter (aTriangulations);
1149            anIter.More(); anIter.Next(), aTriangulationIdx++)
1150       {
1151         if (aTriangulationIdx != theTriangulationIdx)
1152         {
1153           continue;
1154         }
1155         aTriangulation = anIter.Value();
1156         break;
1157       }
1158     }
1159     if (aTriangulation.IsNull() ||
1160        !aTriangulation->HasDeferredData())
1161     {
1162       // NULL triangulation or triangulation without deferred storage cannot be unloaded
1163       continue;
1164     }
1165     wasUnloaded = aTriangulation->UnloadDeferredData();
1166   }
1167   return wasUnloaded;
1168 }
1169
1170 //=======================================================================
1171 //function : UnloadAllTriangulations
1172 //purpose  : 
1173 //=======================================================================
1174 Standard_Boolean BRepTools::UnloadAllTriangulations (const TopoDS_Shape& theShape)
1175 {
1176   Standard_Boolean wasUnloaded = false;
1177   TopLoc_Location aDummyLoc;
1178   for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1179   {
1180     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1181     Handle(Poly_Triangulation) aTriangulation;
1182     for (Poly_ListOfTriangulation::Iterator anIter (BRep_Tool::Triangulations (aFace, aDummyLoc));
1183          anIter.More(); anIter.Next())
1184     {
1185       aTriangulation = anIter.Value();
1186       if (aTriangulation.IsNull() ||
1187          !aTriangulation->HasDeferredData())
1188       {
1189         // NULL triangulation or triangulation without deferred storage cannot be unloaded
1190         continue;
1191       }
1192       wasUnloaded = aTriangulation->UnloadDeferredData();
1193     }
1194   }
1195   return wasUnloaded;
1196 }
1197
1198 //=======================================================================
1199 //function : ActivateTriangulation
1200 //purpose  : 
1201 //=======================================================================
1202 Standard_Boolean BRepTools::ActivateTriangulation (const TopoDS_Shape& theShape,
1203                                                    const Standard_Integer theTriangulationIdx,
1204                                                    const Standard_Boolean theToActivateStrictly)
1205 {
1206   Standard_ASSERT_RAISE (theTriangulationIdx > -1, "Invalid negative triangulation index!");
1207
1208   Standard_Boolean wasActivated = false;
1209   BRep_Builder aBuilder;
1210   TopLoc_Location aDummyLoc;
1211   for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1212   {
1213     const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1214     Standard_Integer aTriangulationIdx = theTriangulationIdx;
1215     const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc);
1216     const Standard_Integer aTriangulationsNb = aTriangulations.Size();
1217     if (theTriangulationIdx >= aTriangulationsNb)
1218     {
1219       // triangulation index is out of range
1220       if (theToActivateStrictly)
1221       {
1222         // skip activation
1223         continue;
1224       }
1225       // use last available
1226       aTriangulationIdx = aTriangulationsNb - 1;
1227     }
1228     Handle(Poly_Triangulation) anActiveTriangulation;
1229     Standard_Integer aTriangulationIter = 0;
1230     for (Poly_ListOfTriangulation::Iterator anIter (aTriangulations);
1231          anIter.More(); anIter.Next(), aTriangulationIter++)
1232     {
1233       if (aTriangulationIter != aTriangulationIdx)
1234       {
1235         continue;
1236       }
1237       anActiveTriangulation = anIter.Value();
1238       break;
1239     }
1240     if (anActiveTriangulation.IsNull())
1241     {
1242       continue;
1243     }
1244     aBuilder.UpdateFace (aFace, anActiveTriangulation, false);
1245     wasActivated = true;
1246   }
1247   return wasActivated;
1248 }
1249
1250 //=======================================================================
1251 //function : IsReallyClosed
1252 //purpose  : 
1253 //=======================================================================
1254
1255 Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
1256                                            const TopoDS_Face& F)
1257 {
1258   if (!BRep_Tool::IsClosed(E,F)) {
1259     return Standard_False;
1260   }
1261   Standard_Integer nbocc = 0;
1262   TopExp_Explorer exp;
1263   for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) {
1264     if (exp.Current().IsSame(E)) {
1265       nbocc++;
1266     }
1267   }
1268   return nbocc == 2;
1269 }
1270
1271 //=======================================================================
1272 //function : DetectClosedness
1273 //purpose  : 
1274 //=======================================================================
1275
1276 void BRepTools::DetectClosedness(const TopoDS_Face& theFace,
1277                                  Standard_Boolean&  theUclosed,
1278                                  Standard_Boolean&  theVclosed)
1279 {
1280   theUclosed = theVclosed = Standard_False;
1281   
1282   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
1283   for (; Explo.More(); Explo.Next())
1284   {
1285     const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
1286     if (BRep_Tool::IsClosed(anEdge, theFace) &&
1287         BRepTools::IsReallyClosed(anEdge, theFace))
1288     {
1289       Standard_Real fpar, lpar;
1290       Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar);
1291       Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(anEdge.Reversed()),
1292                                                                theFace, fpar, lpar);
1293       gp_Pnt2d Point1 = PCurve1->Value(fpar);
1294       gp_Pnt2d Point2 = PCurve2->Value(fpar);
1295       Standard_Boolean IsUiso = (Abs(Point1.X() - Point2.X()) > Abs(Point1.Y() - Point2.Y()));
1296       if (IsUiso)
1297         theUclosed = Standard_True;
1298       else
1299         theVclosed = Standard_True;
1300     }
1301   }
1302 }
1303
1304 //=======================================================================
1305 //function : EvalAndUpdateTol
1306 //purpose  : 
1307 //=======================================================================
1308
1309 Standard_Real BRepTools::EvalAndUpdateTol(const TopoDS_Edge& theE, 
1310                                  const Handle(Geom_Curve)& C3d, 
1311                                  const Handle(Geom2d_Curve) C2d, 
1312                                  const Handle(Geom_Surface)& S,
1313                                  const Standard_Real f,
1314                                  const Standard_Real l)
1315 {
1316   Standard_Real newtol = 0.;
1317   Standard_Real first = f, last = l;
1318   //Set first, last to avoid ErrosStatus = 2 because of 
1319   //too strong checking of limits in class CheckCurveOnSurface
1320   //
1321   if(!C3d->IsPeriodic())
1322   {
1323     first = Max(first, C3d->FirstParameter());
1324     last = Min(last, C3d->LastParameter());
1325   }
1326   if(!C2d->IsPeriodic())
1327   {
1328     first = Max(first, C2d->FirstParameter());
1329     last = Min(last, C2d->LastParameter());
1330   }
1331
1332   GeomLib_CheckCurveOnSurface CT(C3d, S, first, last);
1333   CT.Perform(C2d);
1334   if(CT.IsDone())
1335   {
1336     newtol = CT.MaxDistance();
1337   }
1338   else
1339   {
1340     if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 &&
1341       (C3d->IsPeriodic() || C2d->IsPeriodic())))
1342     {
1343       //Try to estimate by sample points
1344       Standard_Integer nbint = 22;
1345       Standard_Real dt = (last - first) / nbint;
1346       dt = Max(dt, Precision::Confusion());
1347       Standard_Real d, dmax = 0.;
1348       gp_Pnt2d aP2d;
1349       gp_Pnt aPC, aPS;
1350       Standard_Integer cnt = 0; 
1351       Standard_Real t = first;
1352       for(; t <= last; t += dt)
1353       {
1354         cnt++;
1355         C2d->D0(t, aP2d);
1356         C3d->D0(t, aPC);
1357         S->D0(aP2d.X(), aP2d.Y(), aPS);
1358         d = aPS.SquareDistance(aPC);
1359         if(d > dmax)
1360         {
1361           dmax = d;
1362         }
1363       }
1364       if(cnt < nbint + 1)
1365       {
1366         t = last;
1367         C2d->D0(t, aP2d);
1368         C3d->D0(t, aPC);
1369         S->D0(aP2d.X(), aP2d.Y(), aPS);
1370         d = aPS.SquareDistance(aPC);
1371         if(d > dmax)
1372         {
1373           dmax = d;
1374         }
1375       }
1376
1377       newtol = 1.2 * Sqrt(dmax);
1378     }
1379   }
1380   Standard_Real Tol = BRep_Tool::Tolerance(theE);
1381   if(newtol > Tol)
1382   {
1383     Tol = newtol;
1384     BRep_Builder B;
1385     B.UpdateEdge(theE, Tol);
1386   }
1387
1388   return Tol;
1389
1390 }
1391
1392 //=======================================================================
1393 //function : OriEdgeInFace
1394 //purpose  : 
1395 //=======================================================================
1396
1397 TopAbs_Orientation BRepTools::OriEdgeInFace (const TopoDS_Edge& E,
1398                                              const TopoDS_Face& F )
1399
1400 {
1401   TopExp_Explorer Exp(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1402
1403   for (; Exp.More() ;Exp.Next()) {
1404     if (Exp.Current().IsSame(E)) {
1405       return Exp.Current().Orientation();
1406     }
1407   }
1408   throw Standard_ConstructionError("BRepTools::OriEdgeInFace");
1409 }
1410
1411
1412 namespace
1413 {
1414   //=======================================================================
1415   //function : findInternalsToKeep
1416   //purpose  : Looks for internal sub-shapes which has to be kept to preserve
1417   //           topological connectivity.
1418   //=======================================================================
1419   static void findInternalsToKeep (const TopoDS_Shape& theS,
1420                                    TopTools_MapOfShape& theAllNonInternals,
1421                                    TopTools_MapOfShape& theAllInternals,
1422                                    TopTools_MapOfShape& theShapesToKeep)
1423   {
1424     for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next())
1425     {
1426       const TopoDS_Shape& aSS = it.Value();
1427       findInternalsToKeep (aSS, theAllNonInternals, theAllInternals, theShapesToKeep);
1428
1429       if (aSS.Orientation() == TopAbs_INTERNAL)
1430         theAllInternals.Add (aSS);
1431       else
1432         theAllNonInternals.Add (aSS);
1433
1434       if (theAllNonInternals.Contains(aSS) && theAllInternals.Contains (aSS))
1435         theShapesToKeep.Add (aSS);
1436     }
1437   }
1438
1439   //=======================================================================
1440   //function : removeShapes
1441   //purpose  : Removes sub-shapes from the shape
1442   //=======================================================================
1443   static void removeShapes (TopoDS_Shape& theS,
1444                             const TopTools_ListOfShape& theLS)
1445   {
1446     BRep_Builder aBB;
1447     Standard_Boolean isFree = theS.Free();
1448     theS.Free (Standard_True);
1449
1450     for (TopTools_ListOfShape::Iterator it (theLS); it.More(); it.Next())
1451     {
1452       aBB.Remove (theS, it.Value());
1453     }
1454     theS.Free (isFree);
1455   }
1456
1457   //=======================================================================
1458   //function : removeInternals
1459   //purpose  : Removes recursively all internal sub-shapes from the given shape.
1460   //           Returns true if all sub-shapes have been removed from the shape.
1461   //=======================================================================
1462   static Standard_Boolean removeInternals (TopoDS_Shape& theS,
1463                                            const TopTools_MapOfShape* theShapesToKeep)
1464   {
1465     TopTools_ListOfShape aLRemove;
1466     for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next())
1467     {
1468       const TopoDS_Shape& aSS = it.Value();
1469       if (aSS.Orientation() == TopAbs_INTERNAL)
1470       {
1471         if (!theShapesToKeep || !theShapesToKeep->Contains (aSS))
1472           aLRemove.Append (aSS);
1473       }
1474       else
1475       {
1476         if (removeInternals (*(TopoDS_Shape*)&aSS, theShapesToKeep))
1477           aLRemove.Append (aSS);
1478       }
1479     }
1480
1481     Standard_Integer aNbSToRemove = aLRemove.Extent();
1482     if (aNbSToRemove)
1483     {
1484       removeShapes (theS, aLRemove);
1485       return (theS.NbChildren() == 0);
1486     }
1487     return Standard_False;
1488   }
1489
1490 }
1491
1492 //=======================================================================
1493 //function : RemoveInternals
1494 //purpose  : 
1495 //=======================================================================
1496 void BRepTools::RemoveInternals (TopoDS_Shape& theS,
1497                                  const Standard_Boolean theForce)
1498 {
1499   TopTools_MapOfShape *pMKeep = NULL, aMKeep;
1500   if (!theForce)
1501   {
1502     // Find all internal sub-shapes which has to be kept to preserve topological connectivity.
1503     // Note that if the multi-connected shape is not directly contained in some shape,
1504     // but as a part of bigger sub-shape which will be removed, the multi-connected
1505     // shape is going to be removed also, breaking topological connectivity.
1506     // For instance, <theS> is a compound of the face and edge, which does not
1507     // belong to the face. The face contains internal wire and the edge shares
1508     // the vertex with one of the vertices of that wire. The vertex is not directly
1509     // contained in the face, thus will be removed as part of internal wire, and topological
1510     // connectivity between edge and face will be lost.
1511     TopTools_MapOfShape anAllNonInternals, anAllInternals;
1512     findInternalsToKeep (theS, anAllNonInternals, anAllInternals, aMKeep);
1513     if (aMKeep.Extent())
1514       pMKeep = &aMKeep;
1515   }
1516
1517   removeInternals (theS, pMKeep);
1518 }