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