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