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