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