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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
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>
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>
52 #include <TopExp_Explorer.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>
67 //=======================================================================
70 //=======================================================================
71 void BRepTools::UVBounds(const TopoDS_Face& F,
72 Standard_Real& UMin, Standard_Real& UMax,
73 Standard_Real& VMin, Standard_Real& VMax)
77 B.Get(UMin,VMin,UMax,VMax);
80 //=======================================================================
83 //=======================================================================
85 void BRepTools::UVBounds(const TopoDS_Face& F,
87 Standard_Real& UMin, Standard_Real& UMax,
88 Standard_Real& VMin, Standard_Real& VMax)
92 B.Get(UMin,VMin,UMax,VMax);
96 //=======================================================================
99 //=======================================================================
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)
108 B.Get(UMin,VMin,UMax,VMax);
111 //=======================================================================
112 //function : AddUVBounds
114 //=======================================================================
116 void BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B)
119 F.Orientation(TopAbs_FORWARD);
120 TopExp_Explorer ex(F,TopAbs_EDGE);
122 // fill box for the given face
124 for (;ex.More();ex.Next()) {
125 BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),aBox);
128 // if the box is empty (face without edges or without pcurves),
129 // get natural bounds
131 Standard_Real UMin,UMax,VMin,VMax;
133 BRep_Tool::Surface(F,L)->Bounds(UMin,UMax,VMin,VMax);
134 aBox.Update(UMin,VMin,UMax,VMax);
137 // add face box to result
142 //=======================================================================
143 //function : AddUVBounds
145 //=======================================================================
146 void BRepTools::AddUVBounds(const TopoDS_Face& F,
147 const TopoDS_Wire& W,
151 for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) {
152 BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),B);
157 //=======================================================================
158 //function : AddUVBounds
160 //=======================================================================
161 void BRepTools::AddUVBounds(const TopoDS_Face& aF,
162 const TopoDS_Edge& aE,
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;
170 const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
175 BndLib_Add2dCurve::Add(aC2D, aT1, aT2, 0., aBoxC);
176 aBoxC.Get(aXmin, aYmin, aXmax, aYmax);
178 Handle(Geom_Surface) aS = BRep_Tool::Surface(aF, aLoc);
179 aS->Bounds(aUmin, aUmax, aVmin, aVmax);
181 if(aS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
183 const Handle(Geom_RectangularTrimmedSurface) aSt =
184 Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
185 aS = aSt->BasisSurface();
189 if(!aS->IsUPeriodic())
191 Standard_Boolean isUPeriodic = Standard_False;
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))
199 Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
200 isUPeriodic = Standard_True;
202 // 1. Verify that the surface is U-closed
203 if (!aS->IsUClosed())
205 Standard_Real aVStep = aVmax - aVmin;
206 for (Standard_Real aV = aVmin; aV <= aVmax; aV += aVStep)
208 P1 = aS->Value(aUmin, aV);
209 P2 = aS->Value(aUmax, aV);
210 if (P1.SquareDistance(P2) > aTol2)
212 isUPeriodic = Standard_False;
217 // 2. Verify periodicity of surface inside UV-bounds of the edge
218 if (isUPeriodic) // the flag still not changed
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;
227 aU[1] = (aXmin + aUmin) * 0.5;
229 aUpp[0] = aU[0] + aUmax - aUmin;
230 aUpp[1] = aU[1] + aUmax - aUmin;
231 aUpp[2] = aU[2] + aUmax - aUmin;
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;
244 for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
246 P1 = aS->Value(aU[anInd], aV);
247 P2 = aS->Value(aUpp[anInd], aV);
248 if (P1.SquareDistance(P2) > aTol2)
250 isUPeriodic = Standard_False;
259 if((aXmin<aUmin) && (aUmin < aXmax))
263 if((aXmin < aUmax) && (aUmax < aXmax))
270 if(!aS->IsVPeriodic())
272 Standard_Boolean isVPeriodic = Standard_False;
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))
280 Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
281 isVPeriodic = Standard_True;
283 // 1. Verify that the surface is V-closed
284 if (!aS->IsVClosed())
286 Standard_Real aUStep = aUmax - aUmin;
287 for (Standard_Real aU = aUmin; aU <= aUmax; aU += aUStep)
289 P1 = aS->Value(aU, aVmin);
290 P2 = aS->Value(aU, aVmax);
291 if (P1.SquareDistance(P2) > aTol2)
293 isVPeriodic = Standard_False;
298 // 2. Verify periodicity of surface inside UV-bounds of the edge
299 if (isVPeriodic) // the flag still not changed
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;
308 aV[1] = (aYmin + aVmin) * 0.5;
310 aVpp[0] = aV[0] + aVmax - aVmin;
311 aVpp[1] = aV[1] + aVmax - aVmin;
312 aVpp[2] = aV[2] + aVmax - aVmin;
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;
325 for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
327 P1 = aS->Value(aU, aV[anInd]);
328 P2 = aS->Value(aU, aVpp[anInd]);
329 if (P1.SquareDistance(P2) > aTol2)
331 isVPeriodic = Standard_False;
340 if((aYmin<aVmin) && (aVmin < aYmax))
344 if((aYmin < aVmax) && (aVmax < aYmax))
351 aBoxS.Update(aXmin, aYmin, aXmax, aYmax);
356 //=======================================================================
359 //=======================================================================
361 void BRepTools::Update(const TopoDS_Vertex&)
365 //=======================================================================
368 //=======================================================================
370 void BRepTools::Update(const TopoDS_Edge&)
374 //=======================================================================
377 //=======================================================================
379 void BRepTools::Update(const TopoDS_Wire&)
383 //=======================================================================
386 //=======================================================================
388 void BRepTools::Update(const TopoDS_Face& F)
391 UpdateFaceUVPoints(F);
392 F.TShape()->Checked(Standard_True);
396 //=======================================================================
399 //=======================================================================
401 void BRepTools::Update(const TopoDS_Shell& S)
403 TopExp_Explorer ex(S,TopAbs_FACE);
405 Update(TopoDS::Face(ex.Current()));
410 //=======================================================================
413 //=======================================================================
415 void BRepTools::Update(const TopoDS_Solid& S)
417 TopExp_Explorer ex(S,TopAbs_FACE);
419 Update(TopoDS::Face(ex.Current()));
424 //=======================================================================
427 //=======================================================================
429 void BRepTools::Update(const TopoDS_CompSolid& CS)
431 TopExp_Explorer ex(CS,TopAbs_FACE);
433 Update(TopoDS::Face(ex.Current()));
438 //=======================================================================
441 //=======================================================================
443 void BRepTools::Update(const TopoDS_Compound& C)
445 TopExp_Explorer ex(C,TopAbs_FACE);
447 Update(TopoDS::Face(ex.Current()));
452 //=======================================================================
455 //=======================================================================
457 void BRepTools::Update(const TopoDS_Shape& S)
459 switch (S.ShapeType()) {
462 Update(TopoDS::Vertex(S));
466 Update(TopoDS::Edge(S));
470 Update(TopoDS::Wire(S));
474 Update(TopoDS::Face(S));
478 Update(TopoDS::Shell(S));
482 Update(TopoDS::Solid(S));
485 case TopAbs_COMPSOLID :
486 Update(TopoDS::CompSolid(S));
489 case TopAbs_COMPOUND :
490 Update(TopoDS::Compound(S));
500 //=======================================================================
501 //function : UpdateFaceUVPoints
502 //purpose : reset the UV points of a Face
503 //=======================================================================
505 void BRepTools::UpdateFaceUVPoints(const TopoDS_Face& F)
507 // Recompute for each edge the two UV points in order to have the same
508 // UV point on connected edges.
510 // First edge loop, store the vertices in a Map with their 2d points
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;
520 // a 3d tolerance for UV !!
521 Standard_Real tolerance = BRep_Tool::Tolerance(F);
522 TColgp_SequenceOfPnt2d emptySequence;
524 for (expE.Initialize(F); expE.More(); expE.Next()) {
525 if(expE.Value().ShapeType() != TopAbs_WIRE)
528 EdgeIt.Initialize(expE.Value());
529 for( ; EdgeIt.More(); EdgeIt.Next())
531 const TopoDS_Edge& E = TopoDS::Edge(EdgeIt.Value());
533 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,f,l);
540 if (C.IsNull()) continue;
542 for (expV.Initialize(E.Oriented(TopAbs_FORWARD));
543 expV.More(); expV.Next()) {
545 const TopoDS_Vertex& V = TopoDS::Vertex(expV.Value());
547 TopAbs_Orientation Vori = V.Orientation();
548 if ( Vori == TopAbs_INTERNAL ) {
552 Standard_Real p = BRep_Tool::Parameter(V,E,F);
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;
566 // second edge loop, update the edges 2d points
570 for(Standard_Integer j = 1; j <= aShSeq.Length(); j++)
572 const TopoDS_Edge& E = TopoDS::Edge(aShSeq.Value(j));
573 const Handle(Geom2d_Curve)& C = aCSeq.Value(j);
574 if (C.IsNull()) continue;
576 TopExp::Vertices(E,Vf,Vl);
578 Pf.SetCoord(RealLast(),RealLast());
581 if ( Vf.Orientation() == TopAbs_INTERNAL ) {
584 const TColgp_SequenceOfPnt2d& seqf = theVertices(Vf);
585 if (seqf.Length() == 1)
588 C->D0(aFSeq.Value(j),Pf);
589 for (i = 1; i <= seqf.Length(); i++) {
590 if (Pf.Distance(seqf(i)) <= tolerance) {
598 Pl.SetCoord(RealLast(),RealLast());
601 if ( Vl.Orientation() == TopAbs_INTERNAL ) {
604 const TColgp_SequenceOfPnt2d& seql = theVertices(Vl);
605 if (seql.Length() == 1)
608 C->D0(aLSeq.Value(j),Pl);
609 for (i = 1; i <= seql.Length(); i++) {
610 if (Pl.Distance(seql(i)) <= tolerance) {
618 // set the correct points
619 BRep_Tool::SetUVPoints(E,F,Pf,Pl);
625 //=======================================================================
628 //=======================================================================
630 Standard_Boolean BRepTools::Compare(const TopoDS_Vertex& V1,
631 const TopoDS_Vertex& V2)
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;
642 //=======================================================================
645 //=======================================================================
647 Standard_Boolean BRepTools::Compare(const TopoDS_Edge& E1,
648 const TopoDS_Edge& E2)
650 if (E1.IsSame(E2)) return Standard_True;
651 return Standard_False;
654 //=======================================================================
655 //function : OuterWire
657 //=======================================================================
659 TopoDS_Wire BRepTools::OuterWire(const TopoDS_Face& F)
662 TopExp_Explorer expw (F,TopAbs_WIRE);
665 Wres = TopoDS::Wire(expw.Current());
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) &&
691 //=======================================================================
692 //function : Map3DEdges
694 //=======================================================================
696 void BRepTools::Map3DEdges(const TopoDS_Shape& S,
697 TopTools_IndexedMapOfShape& M)
700 for (Ex.Init(S,TopAbs_EDGE); Ex.More(); Ex.Next()) {
701 if (!BRep_Tool::Degenerated(TopoDS::Edge(Ex.Current())))
706 //=======================================================================
709 //=======================================================================
711 void BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
713 BRepTools_ShapeSet SS;
719 //=======================================================================
722 //=======================================================================
724 void BRepTools::Write(const TopoDS_Shape& Sh, Standard_OStream& S,
725 const Handle(Message_ProgressIndicator)& PR)
727 BRepTools_ShapeSet SS;
735 //=======================================================================
738 //=======================================================================
740 void BRepTools::Read(TopoDS_Shape& Sh,
742 const BRep_Builder& B,
743 const Handle(Message_ProgressIndicator)& PR)
745 BRepTools_ShapeSet SS(B);
751 //=======================================================================
754 //=======================================================================
756 Standard_Boolean BRepTools::Write(const TopoDS_Shape& Sh,
757 const Standard_CString File,
758 const Handle(Message_ProgressIndicator)& PR)
761 OSD_OpenStream(os, File, ios::out);
762 if (!os.rdbuf()->is_open()) return Standard_False;
764 Standard_Boolean isGood = (os.good() && !os.eof());
768 BRepTools_ShapeSet SS;
772 os << "DBRep_DrawableShape\n"; // for easy Draw read
782 isGood = os.good() && isGood && !errno;
787 //=======================================================================
790 //=======================================================================
792 Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh,
793 const Standard_CString File,
794 const BRep_Builder& B,
795 const Handle(Message_ProgressIndicator)& PR)
799 OSD_OpenFileBuf(fic,File,ios::in);
800 if(!fic.is_open()) return Standard_False;
802 BRepTools_ShapeSet SS(B);
805 if(!SS.NbShapes()) return Standard_False;
807 return Standard_True;
811 //=======================================================================
814 //=======================================================================
816 void BRepTools::Clean(const TopoDS_Shape& theShape)
818 BRep_Builder aBuilder;
819 Handle(Poly_Triangulation) aNullTriangulation;
820 Handle(Poly_PolygonOnTriangulation) aNullPoly;
822 if (theShape.IsNull())
825 TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
826 for (; aFaceIt.More(); aFaceIt.Next())
828 const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
830 TopLoc_Location aLoc;
831 const Handle(Poly_Triangulation)& aTriangulation =
832 BRep_Tool::Triangulation(aFace, aLoc);
834 if (aTriangulation.IsNull())
838 TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE);
839 for (; aEdgeIt.More(); aEdgeIt.Next())
841 const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
842 aBuilder.UpdateEdge(aEdge, aNullPoly, aTriangulation, aLoc);
845 aBuilder.UpdateFace(aFace, aNullTriangulation);
849 //=======================================================================
850 //function : RemoveUnusedPCurves
852 //=======================================================================
854 void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S)
856 TColStd_MapOfTransient UsedSurfaces;
858 TopExp_Explorer Explo(S, TopAbs_FACE);
859 for (; Explo.More(); Explo.Next())
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);
867 TopTools_IndexedMapOfShape Emap;
868 TopExp::MapShapes(S, TopAbs_EDGE, Emap);
871 for (i = 1; i <= Emap.Extent(); i++)
873 const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape());
874 BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves();
875 BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr );
878 Standard_Boolean ToRemove = Standard_False;
880 Handle(BRep_CurveRepresentation) CurveRep = itrep.Value();
881 if (CurveRep->IsCurveOnSurface())
883 Handle(Geom_Surface) aSurface = CurveRep->Surface();
884 if (!UsedSurfaces.Contains(aSurface))
885 ToRemove = Standard_True;
887 else if (CurveRep->IsRegularity())
889 Handle(Geom_Surface) Surf1 = CurveRep->Surface();
890 Handle(Geom_Surface) Surf2 = CurveRep->Surface2();
891 ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2));
902 //=======================================================================
903 //function : Triangulation
905 //=======================================================================
907 Standard_Boolean BRepTools::Triangulation(const TopoDS_Shape& S,
908 const Standard_Real deflec)
910 TopExp_Explorer exf, exe;
912 Handle(Poly_Triangulation) T;
913 Handle(Poly_PolygonOnTriangulation) Poly;
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;
926 return Standard_True;
930 //=======================================================================
931 //function : IsReallyClosed
933 //=======================================================================
935 Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
936 const TopoDS_Face& F)
938 if (!BRep_Tool::IsClosed(E,F)) {
939 return Standard_False;
941 Standard_Integer nbocc = 0;
943 for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) {
944 if (exp.Current().IsSame(E)) {