diff --git a/src/StdPrs/StdPrs_ShadedShape.cxx b/src/StdPrs/StdPrs_ShadedShape.cxx index b2e1decd96..2d47c6b4bd 100644 --- a/src/StdPrs/StdPrs_ShadedShape.cxx +++ b/src/StdPrs/StdPrs_ShadedShape.cxx @@ -257,7 +257,14 @@ namespace } case TopAbs_SOLID: { - theBuilder.Add (StdPrs_ToolShadedShape::IsClosed (theShape) ? theCompoundForClosed : theCompoundForOpened, theShape); + for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next()) + { + const TopoDS_Shape& aSubShape = anIter.Value(); + const Standard_Boolean isClosed = aSubShape.ShapeType() == TopAbs_SHELL && + BRep_Tool::IsClosed (aSubShape) && + StdPrs_ToolShadedShape::IsTriangulated (aSubShape); + theBuilder.Add (isClosed ? theCompoundForClosed : theCompoundForOpened, aSubShape); + } return; } case TopAbs_SHELL: @@ -483,12 +490,15 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs, // add wireframe presentation for isolated edges and vertices wireframeFromShape (thePrs, theShape, theDrawer); - // IsClosed also verifies triangulation completeness - perform tessellation beforehand + // Triangulation completeness is important for "open-closed" analysis - perform tessellation beforehand Tessellate (theShape, theDrawer); - const Standard_Boolean isClosed = StdPrs_ToolShadedShape::IsClosed (theShape); + + // The shape types listed below need advanced analysis as potentially containing + // both closed and open parts. Solids are also included, because they might + // contain non-manifold parts inside (internal open shells) if ((theShape.ShapeType() == TopAbs_COMPOUND - || theShape.ShapeType() == TopAbs_COMPSOLID) - && !isClosed + || theShape.ShapeType() == TopAbs_COMPSOLID + || theShape.ShapeType() == TopAbs_SOLID) && theToExploreSolids) { // collect two compounds: for opened and closed (solid) sub-shapes @@ -515,7 +525,8 @@ void StdPrs_ShadedShape::Add (const Handle (Prs3d_Presentation)& thePrs, else { shadeFromShape (theShape, thePrs, theDrawer, - theHasTexels, theUVOrigin, theUVRepeat, theUVScale, isClosed); + theHasTexels, theUVOrigin, theUVRepeat, theUVScale, + StdPrs_ToolShadedShape::IsClosed (theShape)); } if (theDrawer->IsFaceBoundaryDraw()) diff --git a/src/StdPrs/StdPrs_ToolShadedShape.cxx b/src/StdPrs/StdPrs_ToolShadedShape.cxx index b1179c2d11..9429b8cda2 100644 --- a/src/StdPrs/StdPrs_ToolShadedShape.cxx +++ b/src/StdPrs/StdPrs_ToolShadedShape.cxx @@ -35,27 +35,23 @@ #include #include -namespace +//======================================================================= +//function : isTriangulated +//purpose : +//======================================================================= +Standard_Boolean StdPrs_ToolShadedShape::IsTriangulated (const TopoDS_Shape& theShape) { - //======================================================================= - //function : isTriangulated - //purpose : Returns true if all faces within shape are triangulated. - // Same as BRepTools::Triangulation() but without extra checks. - //======================================================================= - static Standard_Boolean isTriangulated (const TopoDS_Shape& theShape) + TopLoc_Location aLocDummy; + for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { - TopLoc_Location aLocDummy; - for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) + const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); + const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aLocDummy); + if (aTri.IsNull()) { - const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); - const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aLocDummy); - if (aTri.IsNull()) - { - return Standard_False; - } + return Standard_False; } - return Standard_True; } + return Standard_True; } //======================================================================= @@ -88,6 +84,12 @@ Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape) } case TopAbs_SOLID: { + // Check for non-manifold topology first of all: + // have to use BRep_Tool::IsClosed() because it checks the face connectivity + // inside the shape + if (!BRep_Tool::IsClosed (theShape)) + return Standard_False; + for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next()) { const TopoDS_Shape& aShape = anIter.Value(); @@ -96,17 +98,12 @@ Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape) continue; } - if (aShape.ShapeType() == TopAbs_SHELL - && !aShape.Closed()) - { - return Standard_False; - } - else if (aShape.ShapeType() == TopAbs_FACE) + if (aShape.ShapeType() == TopAbs_FACE) { // invalid solid return Standard_False; } - else if (!isTriangulated (aShape)) + else if (!IsTriangulated (aShape)) { // mesh contains holes return Standard_False; diff --git a/src/StdPrs/StdPrs_ToolShadedShape.hxx b/src/StdPrs/StdPrs_ToolShadedShape.hxx index 76d2a87477..44a9922510 100644 --- a/src/StdPrs/StdPrs_ToolShadedShape.hxx +++ b/src/StdPrs/StdPrs_ToolShadedShape.hxx @@ -32,8 +32,12 @@ public: DEFINE_STANDARD_ALLOC + //! Similar to BRepTools::Triangulation() but without extra checks. + //! @return true if all faces within shape are triangulated. + Standard_EXPORT static Standard_Boolean IsTriangulated (const TopoDS_Shape& theShape); + //! Checks back faces visibility for specified shape (to activate back-face culling).
- //! @return true if shape is closed Solid or compound of closed Solids.
+ //! @return true if shape is closed manifold Solid or compound of such Solids.
Standard_EXPORT static Standard_Boolean IsClosed(const TopoDS_Shape& theShape); Standard_EXPORT static Handle_Poly_Triangulation Triangulation(const TopoDS_Face& aFace, diff --git a/tests/bugs/vis/bug25132 b/tests/bugs/vis/bug25132 new file mode 100644 index 0000000000..192ab749d9 --- /dev/null +++ b/tests/bugs/vis/bug25132 @@ -0,0 +1,34 @@ +puts "============" +puts "OCC25132" +puts "============" +puts "" +#################################################################################### +# Visualization - Capping algorithm not working sometimes +#################################################################################### + +vinit View1 +vsetdispmode 1 +vclipplane create pln1 +vclipplane change pln1 equation 0 1 0 0 +vclipplane change pln1 capping on +vclipplane set pln1 view Driver1/Viewer1/View1 + +# Capping should be enabled for the solid with a bounding shell with Closed flag not set +restore [locate_data_file OCC25132-flight_solid.brep] fs +vdisplay fs +vfit +vdump $imagedir/${casename}_flight_solid.png +vremove fs + +# Capping should be enabled for the solid with cavities +restore [locate_data_file OCC25132-solid_with_cavities.brep] sc +vdisplay sc +vfit +vdump $imagedir/${casename}_solid_with_cavities.png +vremove sc + +# Capping should display a non-manifold solid with an internal open shell correctly +restore [locate_data_file OCC25132-Partition_1.brep] p1 +vdisplay p1 +vfit +vdump $imagedir/${casename}_Partition_1.png diff --git a/tests/mesh/data/standard/P2 b/tests/mesh/data/standard/P2 index c7384eeb8a..1b69799fe7 100755 --- a/tests/mesh/data/standard/P2 +++ b/tests/mesh/data/standard/P2 @@ -1 +1,8 @@ set TheFileName shading_137.brep +if { [string compare ${command} "shading"] == 0 && [string compare ${group} "standard"] == 0 } { + puts "" + puts "CR25132" + puts "san (developer) 2014-08-26 16:59" + puts "The shaded representation looks strange because it is treated as a closed solid by visualization (back faces of the triangles are not drawn)." + puts "" +}