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