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_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>
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 <OSD_OpenFile.hxx>
42 #include <Poly_PolygonOnTriangulation.hxx>
43 #include <Poly_Triangulation.hxx>
44 #include <Precision.hxx>
45 #include <Standard_ErrorHandler.hxx>
46 #include <Standard_Failure.hxx>
47 #include <Standard_Stream.hxx>
48 #include <TColGeom2d_SequenceOfCurve.hxx>
49 #include <TColgp_SequenceOfPnt2d.hxx>
50 #include <TColStd_Array1OfReal.hxx>
51 #include <TColStd_HArray1OfInteger.hxx>
52 #include <TColStd_MapOfTransient.hxx>
53 #include <TColStd_SequenceOfReal.hxx>
55 #include <TopExp_Explorer.hxx>
57 #include <TopoDS_Compound.hxx>
58 #include <TopoDS_CompSolid.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Face.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>
71 //=======================================================================
74 //=======================================================================
75 void BRepTools::UVBounds(const TopoDS_Face& F,
76 Standard_Real& UMin, Standard_Real& UMax,
77 Standard_Real& VMin, Standard_Real& VMax)
83 B.Get(UMin,VMin,UMax,VMax);
87 UMin = UMax = VMin = VMax = 0.0;
91 //=======================================================================
94 //=======================================================================
96 void BRepTools::UVBounds(const TopoDS_Face& F,
98 Standard_Real& UMin, Standard_Real& UMax,
99 Standard_Real& VMin, Standard_Real& VMax)
105 B.Get(UMin,VMin,UMax,VMax);
109 UMin = UMax = VMin = VMax = 0.0;
114 //=======================================================================
115 //function : UVBounds
117 //=======================================================================
119 void BRepTools::UVBounds(const TopoDS_Face& F,
120 const TopoDS_Edge& E,
121 Standard_Real& UMin, Standard_Real& UMax,
122 Standard_Real& VMin, Standard_Real& VMax)
128 B.Get(UMin,VMin,UMax,VMax);
132 UMin = UMax = VMin = VMax = 0.0;
136 //=======================================================================
137 //function : AddUVBounds
139 //=======================================================================
141 void BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B)
144 F.Orientation(TopAbs_FORWARD);
145 TopExp_Explorer ex(F,TopAbs_EDGE);
147 // fill box for the given face
149 for (;ex.More();ex.Next()) {
150 BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),aBox);
153 // if the box is empty (face without edges or without pcurves),
154 // get natural bounds
156 Standard_Real UMin,UMax,VMin,VMax;
158 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, L);
164 aSurf->Bounds(UMin,UMax,VMin,VMax);
165 aBox.Update(UMin,VMin,UMax,VMax);
168 // add face box to result
173 //=======================================================================
174 //function : AddUVBounds
176 //=======================================================================
177 void BRepTools::AddUVBounds(const TopoDS_Face& F,
178 const TopoDS_Wire& W,
182 for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) {
183 BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),B);
188 //=======================================================================
189 //function : AddUVBounds
191 //=======================================================================
192 void BRepTools::AddUVBounds(const TopoDS_Face& aF,
193 const TopoDS_Edge& aE,
196 Standard_Real aT1, aT2, aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0;
197 Standard_Real aUmin, aUmax, aVmin, aVmax;
198 Bnd_Box2d aBoxC, aBoxS;
199 TopLoc_Location aLoc;
201 const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
206 BndLib_Add2dCurve::Add(aC2D, aT1, aT2, 0., aBoxC);
209 aBoxC.Get(aXmin, aYmin, aXmax, aYmax);
212 Handle(Geom_Surface) aS = BRep_Tool::Surface(aF, aLoc);
213 aS->Bounds(aUmin, aUmax, aVmin, aVmax);
215 if(aS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
217 const Handle(Geom_RectangularTrimmedSurface) aSt =
218 Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
219 aS = aSt->BasisSurface();
223 if(!aS->IsUPeriodic())
225 Standard_Boolean isUPeriodic = Standard_False;
227 // Additional verification for U-periodicity for B-spline surfaces
228 // 1. Verify that the surface is U-closed (if such flag is false). Verification uses 2 points
229 // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points.
230 if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) &&
231 (aXmin < aUmin || aXmax > aUmax))
233 Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
234 isUPeriodic = Standard_True;
236 // 1. Verify that the surface is U-closed
237 if (!aS->IsUClosed())
239 Standard_Real aVStep = aVmax - aVmin;
240 for (Standard_Real aV = aVmin; aV <= aVmax; aV += aVStep)
242 P1 = aS->Value(aUmin, aV);
243 P2 = aS->Value(aUmax, aV);
244 if (P1.SquareDistance(P2) > aTol2)
246 isUPeriodic = Standard_False;
251 // 2. Verify periodicity of surface inside UV-bounds of the edge
252 if (isUPeriodic) // the flag still not changed
254 Standard_Real aV = (aVmin + aVmax) * 0.5;
255 Standard_Real aU[6]; // values of U lying out of surface boundaries
256 Standard_Real aUpp[6]; // corresponding U-values plus/minus period
257 Standard_Integer aNbPnt = 0;
261 aU[1] = (aXmin + aUmin) * 0.5;
263 aUpp[0] = aU[0] + aUmax - aUmin;
264 aUpp[1] = aU[1] + aUmax - aUmin;
265 aUpp[2] = aU[2] + aUmax - aUmin;
271 aU[aNbPnt + 1] = (aXmax + aUmax) * 0.5;
272 aU[aNbPnt + 2] = aXmax;
273 aUpp[aNbPnt] = aU[aNbPnt] - aUmax + aUmin;
274 aUpp[aNbPnt + 1] = aU[aNbPnt + 1] - aUmax + aUmin;
275 aUpp[aNbPnt + 2] = aU[aNbPnt + 2] - aUmax + aUmin;
278 for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
280 P1 = aS->Value(aU[anInd], aV);
281 P2 = aS->Value(aUpp[anInd], aV);
282 if (P1.SquareDistance(P2) > aTol2)
284 isUPeriodic = Standard_False;
293 if((aXmin<aUmin) && (aUmin < aXmax))
297 if((aXmin < aUmax) && (aUmax < aXmax))
304 if(!aS->IsVPeriodic())
306 Standard_Boolean isVPeriodic = Standard_False;
308 // Additional verification for V-periodicity for B-spline surfaces
309 // 1. Verify that the surface is V-closed (if such flag is false). Verification uses 2 points
310 // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points.
311 if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) &&
312 (aYmin < aVmin || aYmax > aVmax))
314 Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion();
315 isVPeriodic = Standard_True;
317 // 1. Verify that the surface is V-closed
318 if (!aS->IsVClosed())
320 Standard_Real aUStep = aUmax - aUmin;
321 for (Standard_Real aU = aUmin; aU <= aUmax; aU += aUStep)
323 P1 = aS->Value(aU, aVmin);
324 P2 = aS->Value(aU, aVmax);
325 if (P1.SquareDistance(P2) > aTol2)
327 isVPeriodic = Standard_False;
332 // 2. Verify periodicity of surface inside UV-bounds of the edge
333 if (isVPeriodic) // the flag still not changed
335 Standard_Real aU = (aUmin + aUmax) * 0.5;
336 Standard_Real aV[6]; // values of V lying out of surface boundaries
337 Standard_Real aVpp[6]; // corresponding V-values plus/minus period
338 Standard_Integer aNbPnt = 0;
342 aV[1] = (aYmin + aVmin) * 0.5;
344 aVpp[0] = aV[0] + aVmax - aVmin;
345 aVpp[1] = aV[1] + aVmax - aVmin;
346 aVpp[2] = aV[2] + aVmax - aVmin;
352 aV[aNbPnt + 1] = (aYmax + aVmax) * 0.5;
353 aV[aNbPnt + 2] = aYmax;
354 aVpp[aNbPnt] = aV[aNbPnt] - aVmax + aVmin;
355 aVpp[aNbPnt + 1] = aV[aNbPnt + 1] - aVmax + aVmin;
356 aVpp[aNbPnt + 2] = aV[aNbPnt + 2] - aVmax + aVmin;
359 for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++)
361 P1 = aS->Value(aU, aV[anInd]);
362 P2 = aS->Value(aU, aVpp[anInd]);
363 if (P1.SquareDistance(P2) > aTol2)
365 isVPeriodic = Standard_False;
374 if((aYmin<aVmin) && (aVmin < aYmax))
378 if((aYmin < aVmax) && (aVmax < aYmax))
385 aBoxS.Update(aXmin, aYmin, aXmax, aYmax);
390 //=======================================================================
393 //=======================================================================
395 void BRepTools::Update(const TopoDS_Vertex&)
399 //=======================================================================
402 //=======================================================================
404 void BRepTools::Update(const TopoDS_Edge&)
408 //=======================================================================
411 //=======================================================================
413 void BRepTools::Update(const TopoDS_Wire&)
417 //=======================================================================
420 //=======================================================================
422 void BRepTools::Update(const TopoDS_Face& F)
425 UpdateFaceUVPoints(F);
426 F.TShape()->Checked(Standard_True);
430 //=======================================================================
433 //=======================================================================
435 void BRepTools::Update(const TopoDS_Shell& S)
437 TopExp_Explorer ex(S,TopAbs_FACE);
439 Update(TopoDS::Face(ex.Current()));
444 //=======================================================================
447 //=======================================================================
449 void BRepTools::Update(const TopoDS_Solid& S)
451 TopExp_Explorer ex(S,TopAbs_FACE);
453 Update(TopoDS::Face(ex.Current()));
458 //=======================================================================
461 //=======================================================================
463 void BRepTools::Update(const TopoDS_CompSolid& CS)
465 TopExp_Explorer ex(CS,TopAbs_FACE);
467 Update(TopoDS::Face(ex.Current()));
472 //=======================================================================
475 //=======================================================================
477 void BRepTools::Update(const TopoDS_Compound& C)
479 TopExp_Explorer ex(C,TopAbs_FACE);
481 Update(TopoDS::Face(ex.Current()));
486 //=======================================================================
489 //=======================================================================
491 void BRepTools::Update(const TopoDS_Shape& S)
493 switch (S.ShapeType()) {
496 Update(TopoDS::Vertex(S));
500 Update(TopoDS::Edge(S));
504 Update(TopoDS::Wire(S));
508 Update(TopoDS::Face(S));
512 Update(TopoDS::Shell(S));
516 Update(TopoDS::Solid(S));
519 case TopAbs_COMPSOLID :
520 Update(TopoDS::CompSolid(S));
523 case TopAbs_COMPOUND :
524 Update(TopoDS::Compound(S));
533 //=======================================================================
534 //function : UpdateFaceUVPoints
535 //purpose : Reset the UV points of edges on the Face
536 //=======================================================================
537 void BRepTools::UpdateFaceUVPoints(const TopoDS_Face& theF)
539 // For each edge of the face <F> reset the UV points to the bounding
540 // points of the parametric curve of the edge on the face.
542 // Get surface of the face
543 TopLoc_Location aLoc;
544 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(theF, aLoc);
545 // Iterate on edges and reset UV points
546 TopExp_Explorer anExpE(theF, TopAbs_EDGE);
547 for (; anExpE.More(); anExpE.Next())
549 const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
551 const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
555 const TopLoc_Location aELoc = aLoc.Predivided(aE.Location());
556 // Edge representations
557 BRep_ListOfCurveRepresentation& aLCR = TE->ChangeCurves();
558 BRep_ListIteratorOfListOfCurveRepresentation itLCR(aLCR);
559 for (; itLCR.More(); itLCR.Next())
561 Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itLCR.Value());
562 if (!GC.IsNull() && GC->IsCurveOnSurface(aSurf, aELoc))
572 //=======================================================================
575 //=======================================================================
577 Standard_Boolean BRepTools::Compare(const TopoDS_Vertex& V1,
578 const TopoDS_Vertex& V2)
580 if (V1.IsSame(V2)) return Standard_True;
581 gp_Pnt p1 = BRep_Tool::Pnt(V1);
582 gp_Pnt p2 = BRep_Tool::Pnt(V2);
583 Standard_Real l = p1.Distance(p2);
584 if (l <= BRep_Tool::Tolerance(V1)) return Standard_True;
585 if (l <= BRep_Tool::Tolerance(V2)) return Standard_True;
586 return Standard_False;
589 //=======================================================================
592 //=======================================================================
594 Standard_Boolean BRepTools::Compare(const TopoDS_Edge& E1,
595 const TopoDS_Edge& E2)
597 if (E1.IsSame(E2)) return Standard_True;
598 return Standard_False;
601 //=======================================================================
602 //function : OuterWire
604 //=======================================================================
606 TopoDS_Wire BRepTools::OuterWire(const TopoDS_Face& F)
609 TopExp_Explorer expw (F,TopAbs_WIRE);
612 Wres = TopoDS::Wire(expw.Current());
615 Standard_Real UMin, UMax, VMin, VMax;
616 Standard_Real umin, umax, vmin, vmax;
617 BRepTools::UVBounds(F,Wres,UMin,UMax,VMin,VMax);
618 while (expw.More()) {
619 const TopoDS_Wire& W = TopoDS::Wire(expw.Current());
620 BRepTools::UVBounds(F,W,umin, umax, vmin, vmax);
621 if (((umin - UMin) <= Precision::PConfusion()) &&
622 ((umax - UMax) >= -Precision::PConfusion()) &&
623 ((vmin - VMin) <= Precision::PConfusion()) &&
624 ((vmax - VMax) >= -Precision::PConfusion())) {
638 //=======================================================================
639 //function : Map3DEdges
641 //=======================================================================
643 void BRepTools::Map3DEdges(const TopoDS_Shape& S,
644 TopTools_IndexedMapOfShape& M)
647 for (Ex.Init(S,TopAbs_EDGE); Ex.More(); Ex.Next()) {
648 if (!BRep_Tool::Degenerated(TopoDS::Edge(Ex.Current())))
653 //=======================================================================
656 //=======================================================================
658 void BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S)
660 BRepTools_ShapeSet SS;
666 //=======================================================================
669 //=======================================================================
670 void BRepTools::Write (const TopoDS_Shape& theShape,
671 Standard_OStream& theStream,
672 const Standard_Boolean theWithTriangles,
673 const Standard_Boolean theWithNormals,
674 const TopTools_FormatVersion theVersion,
675 const Message_ProgressRange& theProgress)
677 BRepTools_ShapeSet aShapeSet (theWithTriangles, theWithNormals);
678 aShapeSet.SetFormatNb (theVersion);
679 aShapeSet.Add (theShape);
680 aShapeSet.Write (theStream, theProgress);
681 aShapeSet.Write (theShape, theStream);
684 //=======================================================================
687 //=======================================================================
689 void BRepTools::Read(TopoDS_Shape& Sh,
691 const BRep_Builder& B,
692 const Message_ProgressRange& theProgress)
694 BRepTools_ShapeSet SS(B);
695 SS.Read(S, theProgress);
699 //=======================================================================
702 //=======================================================================
703 Standard_Boolean BRepTools::Write (const TopoDS_Shape& theShape,
704 const Standard_CString theFile,
705 const Standard_Boolean theWithTriangles,
706 const Standard_Boolean theWithNormals,
707 const TopTools_FormatVersion theVersion,
708 const Message_ProgressRange& theProgress)
711 OSD_OpenStream(os, theFile, std::ios::out);
712 if (!os.is_open() || !os.good())
713 return Standard_False;
715 Standard_Boolean isGood = (os.good() && !os.eof());
719 BRepTools_ShapeSet SS (theWithTriangles, theWithNormals);
720 SS.SetFormatNb (theVersion);
723 os << "DBRep_DrawableShape\n"; // for easy Draw read
724 SS.Write(os, theProgress);
728 SS.Write (theShape, os);
735 isGood = os.good() && isGood && !errno;
740 //=======================================================================
743 //=======================================================================
745 Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh,
746 const Standard_CString File,
747 const BRep_Builder& B,
748 const Message_ProgressRange& theProgress)
751 std::istream in(&fic);
752 OSD_OpenStream (fic, File, std::ios::in);
753 if(!fic.is_open()) return Standard_False;
755 BRepTools_ShapeSet SS(B);
756 SS.Read(in, theProgress);
757 if(!SS.NbShapes()) return Standard_False;
759 return Standard_True;
763 //=======================================================================
766 //=======================================================================
768 void BRepTools::Clean (const TopoDS_Shape& theShape, const Standard_Boolean theForce)
770 if (theShape.IsNull())
773 BRep_Builder aBuilder;
774 Handle(Poly_Triangulation) aNullTriangulation;
775 Handle(Poly_PolygonOnTriangulation) aNullPoly;
777 TopTools_MapOfShape aShapeMap;
778 const TopLoc_Location anEmptyLoc;
780 TopExp_Explorer aFaceIt(theShape, TopAbs_FACE);
781 for (; aFaceIt.More(); aFaceIt.Next())
783 TopoDS_Shape aFaceNoLoc = aFaceIt.Value();
784 aFaceNoLoc.Location (anEmptyLoc);
785 if (!aShapeMap.Add (aFaceNoLoc))
787 // the face has already been processed
791 const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
792 if (!BRep_Tool::IsGeometric (aFace))
794 // Do not remove triangulation as there is no surface to recompute it.
799 TopLoc_Location aLoc;
800 const Handle(Poly_Triangulation)& aTriangulation =
801 BRep_Tool::Triangulation(aFace, aLoc);
803 if (aTriangulation.IsNull())
807 // Theoretically, the edges on the face (with surface) may have no geometry
808 // (no curve 3d or 2d or both). Such faces should be considered as invalid and
809 // are not supported by current implementation. So, both triangulation of the face
810 // and polygon on triangulation of the edges are removed unconditionally.
811 TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE);
812 for (; aEdgeIt.More(); aEdgeIt.Next())
814 const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current());
815 aBuilder.UpdateEdge(anEdge, aNullPoly, aTriangulation, aLoc);
818 aBuilder.UpdateFace(aFace, aNullTriangulation);
821 // Iterate over all edges seeking for 3d polygons
822 Handle (Poly_Polygon3D) aNullPoly3d;
823 TopExp_Explorer aEdgeIt (theShape, TopAbs_EDGE);
824 for (; aEdgeIt.More (); aEdgeIt.Next ())
826 TopoDS_Edge anEdge = TopoDS::Edge(aEdgeIt.Value());
827 anEdge.Location(anEmptyLoc);
829 if (!aShapeMap.Add(anEdge))
831 // the edge has already been processed
835 if (!BRep_Tool::IsGeometric(TopoDS::Edge(anEdge)))
837 // Do not remove polygon 3d as there is no curve to recompute it.
841 TopLoc_Location aLoc;
842 Handle(Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D(anEdge, aLoc);
844 if (!aPoly3d.IsNull())
846 aBuilder.UpdateEdge(anEdge, aNullPoly3d);
850 Handle(BRep_CurveRepresentation) aCR;
851 BRep_TEdge* aTE = static_cast<BRep_TEdge*>(anEdge.TShape().get());
852 BRep_ListOfCurveRepresentation& aLCR = aTE->ChangeCurves();
853 BRep_ListIteratorOfListOfCurveRepresentation anIterCR(aLCR);
855 // find and remove all representations
856 while (anIterCR.More())
858 aCR = anIterCR.Value();
859 if (aCR->IsPolygonOnTriangulation())
861 aLCR.Remove(anIterCR);
868 aTE->Modified(Standard_True);
872 //=======================================================================
873 //function : CleanGeometry
875 //=======================================================================
877 void BRepTools::CleanGeometry(const TopoDS_Shape& theShape)
879 if (theShape.IsNull())
882 BRep_Builder aBuilder;
884 for (TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
886 TopLoc_Location aLocation;
887 const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
888 const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(aFace, aLocation);
890 for (TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE); aEdgeIt.More(); aEdgeIt.Next())
892 const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current());
893 aBuilder.UpdateEdge(anEdge, Handle(Geom2d_Curve)(), aSurface,
894 aLocation, BRep_Tool::Tolerance(anEdge));
897 aBuilder.UpdateFace(aFace, Handle(Geom_Surface)(), aFace.Location(), BRep_Tool::Tolerance(aFace));
900 for (TopExp_Explorer aEdgeIt2(theShape, TopAbs_EDGE); aEdgeIt2.More(); aEdgeIt2.Next())
902 const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt2.Current());
903 aBuilder.UpdateEdge(anEdge, Handle(Geom_Curve)(),
904 TopLoc_Location(), BRep_Tool::Tolerance(anEdge));
909 //=======================================================================
910 //function : RemoveUnusedPCurves
912 //=======================================================================
914 void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S)
916 TColStd_MapOfTransient UsedSurfaces;
918 TopExp_Explorer Explo(S, TopAbs_FACE);
919 for (; Explo.More(); Explo.Next())
921 TopoDS_Face aFace = TopoDS::Face(Explo.Current());
922 TopLoc_Location aLoc;
923 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
924 UsedSurfaces.Add(aSurf);
927 TopTools_IndexedMapOfShape Emap;
928 TopExp::MapShapes(S, TopAbs_EDGE, Emap);
931 for (i = 1; i <= Emap.Extent(); i++)
933 const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape());
934 BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves();
935 BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr );
938 Standard_Boolean ToRemove = Standard_False;
940 Handle(BRep_CurveRepresentation) CurveRep = itrep.Value();
941 if (CurveRep->IsCurveOnSurface())
943 Handle(Geom_Surface) aSurface = CurveRep->Surface();
944 if (!UsedSurfaces.Contains(aSurface))
945 ToRemove = Standard_True;
947 else if (CurveRep->IsRegularity())
949 Handle(Geom_Surface) Surf1 = CurveRep->Surface();
950 Handle(Geom_Surface) Surf2 = CurveRep->Surface2();
951 ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2));
962 //=======================================================================
963 //function : Triangulation
965 //=======================================================================
967 Standard_Boolean BRepTools::Triangulation(const TopoDS_Shape& theShape,
968 const Standard_Real theLinDefl,
969 const Standard_Boolean theToCheckFreeEdges)
971 TopExp_Explorer anEdgeIter;
972 TopLoc_Location aDummyLoc;
973 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
975 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
976 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aDummyLoc);
978 || aTri->Deflection() > theLinDefl)
980 return Standard_False;
983 for (anEdgeIter.Init (aFace, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next())
985 const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current());
986 const Handle(Poly_PolygonOnTriangulation)& aPoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTri, aDummyLoc);
989 return Standard_False;
993 if (!theToCheckFreeEdges)
995 return Standard_True;
998 Handle(Poly_Triangulation) anEdgeTri;
999 for (anEdgeIter.Init (theShape, TopAbs_EDGE, TopAbs_FACE); anEdgeIter.More(); anEdgeIter.Next())
1001 const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current());
1002 const Handle(Poly_Polygon3D)& aPolygon = BRep_Tool::Polygon3D (anEdge, aDummyLoc);
1003 if (!aPolygon.IsNull())
1005 if (aPolygon->Deflection() > theLinDefl)
1007 return Standard_False;
1012 const Handle(Poly_PolygonOnTriangulation)& aPoly = BRep_Tool::PolygonOnTriangulation (anEdge, anEdgeTri, aDummyLoc);
1014 || anEdgeTri.IsNull()
1015 || anEdgeTri->Deflection() > theLinDefl)
1017 return Standard_False;
1022 return Standard_True;
1025 //=======================================================================
1026 //function : LoadTriangulation
1028 //=======================================================================
1029 Standard_Boolean BRepTools::LoadTriangulation (const TopoDS_Shape& theShape,
1030 const Standard_Integer theTriangulationIdx,
1031 const Standard_Boolean theToSetAsActive,
1032 const Handle(OSD_FileSystem)& theFileSystem)
1034 Standard_ASSERT_RAISE (theTriangulationIdx >= -1, "Invalid negative triangulation index!");
1036 Standard_Boolean wasLoaded = false;
1037 BRep_Builder aBuilder;
1038 TopLoc_Location aDummyLoc;
1039 const Handle(OSD_FileSystem)& aFileSystem = !theFileSystem.IsNull() ? theFileSystem : OSD_FileSystem::DefaultFileSystem();
1040 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1042 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1043 Handle(Poly_Triangulation) aTriangulation;
1044 if (theTriangulationIdx == -1)
1046 // load an active triangulation
1047 aTriangulation = BRep_Tool::Triangulation (aFace, aDummyLoc);
1051 const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc);
1052 if (theTriangulationIdx >= aTriangulations.Size())
1054 // triangulation index is out of range
1057 Standard_Integer aTriangulationIdx = 0;
1058 for (Poly_ListOfTriangulation::Iterator anIter(aTriangulations);
1059 anIter.More(); anIter.Next(), aTriangulationIdx++)
1061 if (aTriangulationIdx != theTriangulationIdx)
1065 aTriangulation = anIter.Value();
1069 if (aTriangulation.IsNull() ||
1070 !aTriangulation->HasDeferredData())
1072 // NULL triangulation, already loaded triangulation or triangulation without deferred storage
1076 if (aTriangulation->LoadDeferredData (aFileSystem))
1079 if (theToSetAsActive
1080 && (theTriangulationIdx != -1)) // triangulation is already active
1082 aBuilder.UpdateFace (aFace, aTriangulation, false);
1089 //=======================================================================
1090 //function : LoadAllTriangulation
1092 //=======================================================================
1093 Standard_Boolean BRepTools::LoadAllTriangulations (const TopoDS_Shape& theShape,
1094 const Handle(OSD_FileSystem)& theFileSystem)
1096 Standard_Boolean wasLoaded = false;
1097 TopLoc_Location aDummyLoc;
1098 const Handle(OSD_FileSystem)& aFileSystem = !theFileSystem.IsNull() ? theFileSystem : OSD_FileSystem::DefaultFileSystem();
1099 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1101 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1102 for (Poly_ListOfTriangulation::Iterator anIter (BRep_Tool::Triangulations (aFace, aDummyLoc));
1103 anIter.More(); anIter.Next())
1105 const Handle(Poly_Triangulation)& aTriangulation = anIter.Value();
1106 if (aTriangulation.IsNull() ||
1107 !aTriangulation->HasDeferredData())
1109 // NULL triangulation, already loaded triangulation or triangulation without deferred storage
1113 wasLoaded = aTriangulation->LoadDeferredData (aFileSystem);
1119 //=======================================================================
1120 //function : UnloadTriangulation
1122 //=======================================================================
1123 Standard_Boolean BRepTools::UnloadTriangulation (const TopoDS_Shape& theShape,
1124 const Standard_Integer theTriangulationIdx)
1126 Standard_ASSERT_RAISE (theTriangulationIdx >= -1, "Invalid negative triangulation index!");
1128 Standard_Boolean wasUnloaded = false;
1129 TopLoc_Location aDummyLoc;
1130 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1132 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1133 Handle(Poly_Triangulation) aTriangulation;
1134 if (theTriangulationIdx == -1)
1136 // unload an active triangulation
1137 aTriangulation = BRep_Tool::Triangulation (aFace, aDummyLoc);
1141 Standard_Integer aTriangulationIdx = 0;
1142 const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc);
1143 if (theTriangulationIdx >= aTriangulations.Size())
1145 // triangulation index is out of range
1148 for (Poly_ListOfTriangulation::Iterator anIter (aTriangulations);
1149 anIter.More(); anIter.Next(), aTriangulationIdx++)
1151 if (aTriangulationIdx != theTriangulationIdx)
1155 aTriangulation = anIter.Value();
1159 if (aTriangulation.IsNull() ||
1160 !aTriangulation->HasDeferredData())
1162 // NULL triangulation or triangulation without deferred storage cannot be unloaded
1165 wasUnloaded = aTriangulation->UnloadDeferredData();
1170 //=======================================================================
1171 //function : UnloadAllTriangulations
1173 //=======================================================================
1174 Standard_Boolean BRepTools::UnloadAllTriangulations (const TopoDS_Shape& theShape)
1176 Standard_Boolean wasUnloaded = false;
1177 TopLoc_Location aDummyLoc;
1178 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1180 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1181 Handle(Poly_Triangulation) aTriangulation;
1182 for (Poly_ListOfTriangulation::Iterator anIter (BRep_Tool::Triangulations (aFace, aDummyLoc));
1183 anIter.More(); anIter.Next())
1185 aTriangulation = anIter.Value();
1186 if (aTriangulation.IsNull() ||
1187 !aTriangulation->HasDeferredData())
1189 // NULL triangulation or triangulation without deferred storage cannot be unloaded
1192 wasUnloaded = aTriangulation->UnloadDeferredData();
1198 //=======================================================================
1199 //function : ActivateTriangulation
1201 //=======================================================================
1202 Standard_Boolean BRepTools::ActivateTriangulation (const TopoDS_Shape& theShape,
1203 const Standard_Integer theTriangulationIdx,
1204 const Standard_Boolean theToActivateStrictly)
1206 Standard_ASSERT_RAISE (theTriangulationIdx > -1, "Invalid negative triangulation index!");
1208 Standard_Boolean wasActivated = false;
1209 BRep_Builder aBuilder;
1210 TopLoc_Location aDummyLoc;
1211 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1213 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
1214 Standard_Integer aTriangulationIdx = theTriangulationIdx;
1215 const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc);
1216 const Standard_Integer aTriangulationsNb = aTriangulations.Size();
1217 if (theTriangulationIdx >= aTriangulationsNb)
1219 // triangulation index is out of range
1220 if (theToActivateStrictly)
1225 // use last available
1226 aTriangulationIdx = aTriangulationsNb - 1;
1228 Handle(Poly_Triangulation) anActiveTriangulation;
1229 Standard_Integer aTriangulationIter = 0;
1230 for (Poly_ListOfTriangulation::Iterator anIter (aTriangulations);
1231 anIter.More(); anIter.Next(), aTriangulationIter++)
1233 if (aTriangulationIter != aTriangulationIdx)
1237 anActiveTriangulation = anIter.Value();
1240 if (anActiveTriangulation.IsNull())
1244 aBuilder.UpdateFace (aFace, anActiveTriangulation, false);
1245 wasActivated = true;
1247 return wasActivated;
1250 //=======================================================================
1251 //function : IsReallyClosed
1253 //=======================================================================
1255 Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E,
1256 const TopoDS_Face& F)
1258 if (!BRep_Tool::IsClosed(E,F)) {
1259 return Standard_False;
1261 Standard_Integer nbocc = 0;
1262 TopExp_Explorer exp;
1263 for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) {
1264 if (exp.Current().IsSame(E)) {
1271 //=======================================================================
1272 //function : DetectClosedness
1274 //=======================================================================
1276 void BRepTools::DetectClosedness(const TopoDS_Face& theFace,
1277 Standard_Boolean& theUclosed,
1278 Standard_Boolean& theVclosed)
1280 theUclosed = theVclosed = Standard_False;
1282 TopExp_Explorer Explo(theFace, TopAbs_EDGE);
1283 for (; Explo.More(); Explo.Next())
1285 const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
1286 if (BRep_Tool::IsClosed(anEdge, theFace) &&
1287 BRepTools::IsReallyClosed(anEdge, theFace))
1289 Standard_Real fpar, lpar;
1290 Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar);
1291 Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(anEdge.Reversed()),
1292 theFace, fpar, lpar);
1293 gp_Pnt2d Point1 = PCurve1->Value(fpar);
1294 gp_Pnt2d Point2 = PCurve2->Value(fpar);
1295 Standard_Boolean IsUiso = (Abs(Point1.X() - Point2.X()) > Abs(Point1.Y() - Point2.Y()));
1297 theUclosed = Standard_True;
1299 theVclosed = Standard_True;
1304 //=======================================================================
1305 //function : EvalAndUpdateTol
1307 //=======================================================================
1309 Standard_Real BRepTools::EvalAndUpdateTol(const TopoDS_Edge& theE,
1310 const Handle(Geom_Curve)& C3d,
1311 const Handle(Geom2d_Curve) C2d,
1312 const Handle(Geom_Surface)& S,
1313 const Standard_Real f,
1314 const Standard_Real l)
1316 Standard_Real newtol = 0.;
1317 Standard_Real first = f, last = l;
1318 //Set first, last to avoid ErrosStatus = 2 because of
1319 //too strong checking of limits in class CheckCurveOnSurface
1321 if(!C3d->IsPeriodic())
1323 first = Max(first, C3d->FirstParameter());
1324 last = Min(last, C3d->LastParameter());
1326 if(!C2d->IsPeriodic())
1328 first = Max(first, C2d->FirstParameter());
1329 last = Min(last, C2d->LastParameter());
1332 GeomLib_CheckCurveOnSurface CT(C3d, S, first, last);
1336 newtol = CT.MaxDistance();
1340 if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 &&
1341 (C3d->IsPeriodic() || C2d->IsPeriodic())))
1343 //Try to estimate by sample points
1344 Standard_Integer nbint = 22;
1345 Standard_Real dt = (last - first) / nbint;
1346 dt = Max(dt, Precision::Confusion());
1347 Standard_Real d, dmax = 0.;
1350 Standard_Integer cnt = 0;
1351 Standard_Real t = first;
1352 for(; t <= last; t += dt)
1357 S->D0(aP2d.X(), aP2d.Y(), aPS);
1358 d = aPS.SquareDistance(aPC);
1369 S->D0(aP2d.X(), aP2d.Y(), aPS);
1370 d = aPS.SquareDistance(aPC);
1377 newtol = 1.2 * Sqrt(dmax);
1380 Standard_Real Tol = BRep_Tool::Tolerance(theE);
1385 B.UpdateEdge(theE, Tol);
1392 //=======================================================================
1393 //function : OriEdgeInFace
1395 //=======================================================================
1397 TopAbs_Orientation BRepTools::OriEdgeInFace (const TopoDS_Edge& E,
1398 const TopoDS_Face& F )
1401 TopExp_Explorer Exp(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1403 for (; Exp.More() ;Exp.Next()) {
1404 if (Exp.Current().IsSame(E)) {
1405 return Exp.Current().Orientation();
1408 throw Standard_ConstructionError("BRepTools::OriEdgeInFace");
1414 //=======================================================================
1415 //function : findInternalsToKeep
1416 //purpose : Looks for internal sub-shapes which has to be kept to preserve
1417 // topological connectivity.
1418 //=======================================================================
1419 static void findInternalsToKeep (const TopoDS_Shape& theS,
1420 TopTools_MapOfShape& theAllNonInternals,
1421 TopTools_MapOfShape& theAllInternals,
1422 TopTools_MapOfShape& theShapesToKeep)
1424 for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next())
1426 const TopoDS_Shape& aSS = it.Value();
1427 findInternalsToKeep (aSS, theAllNonInternals, theAllInternals, theShapesToKeep);
1429 if (aSS.Orientation() == TopAbs_INTERNAL)
1430 theAllInternals.Add (aSS);
1432 theAllNonInternals.Add (aSS);
1434 if (theAllNonInternals.Contains(aSS) && theAllInternals.Contains (aSS))
1435 theShapesToKeep.Add (aSS);
1439 //=======================================================================
1440 //function : removeShapes
1441 //purpose : Removes sub-shapes from the shape
1442 //=======================================================================
1443 static void removeShapes (TopoDS_Shape& theS,
1444 const TopTools_ListOfShape& theLS)
1447 Standard_Boolean isFree = theS.Free();
1448 theS.Free (Standard_True);
1450 for (TopTools_ListOfShape::Iterator it (theLS); it.More(); it.Next())
1452 aBB.Remove (theS, it.Value());
1457 //=======================================================================
1458 //function : removeInternals
1459 //purpose : Removes recursively all internal sub-shapes from the given shape.
1460 // Returns true if all sub-shapes have been removed from the shape.
1461 //=======================================================================
1462 static Standard_Boolean removeInternals (TopoDS_Shape& theS,
1463 const TopTools_MapOfShape* theShapesToKeep)
1465 TopTools_ListOfShape aLRemove;
1466 for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next())
1468 const TopoDS_Shape& aSS = it.Value();
1469 if (aSS.Orientation() == TopAbs_INTERNAL)
1471 if (!theShapesToKeep || !theShapesToKeep->Contains (aSS))
1472 aLRemove.Append (aSS);
1476 if (removeInternals (*(TopoDS_Shape*)&aSS, theShapesToKeep))
1477 aLRemove.Append (aSS);
1481 Standard_Integer aNbSToRemove = aLRemove.Extent();
1484 removeShapes (theS, aLRemove);
1485 return (theS.NbChildren() == 0);
1487 return Standard_False;
1492 //=======================================================================
1493 //function : RemoveInternals
1495 //=======================================================================
1496 void BRepTools::RemoveInternals (TopoDS_Shape& theS,
1497 const Standard_Boolean theForce)
1499 TopTools_MapOfShape *pMKeep = NULL, aMKeep;
1502 // Find all internal sub-shapes which has to be kept to preserve topological connectivity.
1503 // Note that if the multi-connected shape is not directly contained in some shape,
1504 // but as a part of bigger sub-shape which will be removed, the multi-connected
1505 // shape is going to be removed also, breaking topological connectivity.
1506 // For instance, <theS> is a compound of the face and edge, which does not
1507 // belong to the face. The face contains internal wire and the edge shares
1508 // the vertex with one of the vertices of that wire. The vertex is not directly
1509 // contained in the face, thus will be removed as part of internal wire, and topological
1510 // connectivity between edge and face will be lost.
1511 TopTools_MapOfShape anAllNonInternals, anAllInternals;
1512 findInternalsToKeep (theS, anAllNonInternals, anAllInternals, aMKeep);
1513 if (aMKeep.Extent())
1517 removeInternals (theS, pMKeep);