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