From e6a11fa375677eb0284c3f1264c0169abcdfd26c Mon Sep 17 00:00:00 2001 From: drochalo Date: Thu, 19 Oct 2023 16:35:09 +0100 Subject: [PATCH] 0021753: Visualization - improve shaded display of conical objects Update on the method to solve cone apex point issue. Revamped previous solution proposed on CR21753 branch. --- src/StdPrs/StdPrs_ShadedShape.cxx | 164 ++++++++++++++++++++++++------ 1 file changed, 132 insertions(+), 32 deletions(-) diff --git a/src/StdPrs/StdPrs_ShadedShape.cxx b/src/StdPrs/StdPrs_ShadedShape.cxx index 3e56277c1b..b0ec5ca7d2 100644 --- a/src/StdPrs/StdPrs_ShadedShape.cxx +++ b/src/StdPrs/StdPrs_ShadedShape.cxx @@ -133,6 +133,47 @@ namespace } } + //! Auxiliary function searching the degenerated node in the triangle. + //! Returns index of node in triangle (0, 1, 2) or -1 if degenerated node is not found. + Standard_Integer findDegenNodeInTri(const Handle(Poly_PolygonOnTriangulation)& theDegenPolygon, + const Standard_Integer* theTriNodeInd) + { + if (theTriNodeInd[0] == theDegenPolygon->Nodes().First() + || theTriNodeInd[0] == theDegenPolygon->Nodes().Last()) + { + return 0; + } + else if (theTriNodeInd[1] == theDegenPolygon->Nodes().First() + || theTriNodeInd[1] == theDegenPolygon->Nodes().Last()) + { + return 1; + } + else if (theTriNodeInd[2] == theDegenPolygon->Nodes().First() + || theTriNodeInd[2] == theDegenPolygon->Nodes().Last()) + { + return 2; + } + return -1; + } + + //! Auxiliary function searching the degenerated node in the triangle. + //! Returns index of node in triangle (0, 1, 2) or -1 if degenerated node is not found. + Standard_Integer findDegenNodeInTri(const NCollection_Sequence& thePolygons, + const Standard_Integer* theTriNodeInd) + { + Standard_Integer aTriNode = -1; + for (NCollection_Sequence::Iterator anIter(thePolygons); + anIter.More(); anIter.Next()) + { + aTriNode = findDegenNodeInTri(anIter.Value(), theTriNodeInd); + if (aTriNode != -1) + { + return aTriNode; + } + } + return -1; + } + //! Gets triangulation of every face of shape and fills output array of triangles static Handle(Graphic3d_ArrayOfTriangles) fillTriangles (const TopoDS_Shape& theShape, const Standard_Boolean theHasTexels, @@ -141,10 +182,12 @@ namespace const gp_Pnt2d& theUVScale) { Handle(Poly_Triangulation) aT; - TopLoc_Location aLoc; + TopLoc_Location aLoc, aLocDummy; gp_Pnt aPoint; Standard_Integer aNbTriangles = 0; Standard_Integer aNbVertices = 0; + Standard_Integer aNbDupNodes = 0; + Standard_Integer anIndex[3]; // Precision for compare square distances const Standard_Real aPreci = Precision::SquareConfusion(); @@ -154,12 +197,44 @@ namespace { const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); aT = BRep_Tool::Triangulation (aFace, aLoc); - if (!aT.IsNull()) + //if (!aT.IsNull()) + //{ + // aNbTriangles += aT->NbTriangles(); + // aNbVertices += aT->NbNodes(); + //} + if (aT.IsNull()) { - aNbTriangles += aT->NbTriangles(); - aNbVertices += aT->NbNodes(); + continue; + } + + aNbTriangles += aT->NbTriangles(); + aNbVertices += aT->NbNodes(); + + // estimate number of degenerated nodes to be duplicated + for (TopExp_Explorer anEdgeIt(aFace, TopAbs_EDGE); anEdgeIt.More(); anEdgeIt.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(anEdgeIt.Current()); + if (BRep_Tool::Degenerated(anEdge)) + { + Handle(Poly_PolygonOnTriangulation) anEdgePoly = BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLocDummy); + if (anEdgePoly.IsNull()) + { + continue; + } + + for (Standard_Integer aTriIter = 1; aTriIter <= aT->NbTriangles(); ++aTriIter) + { + aT->Triangle(aTriIter).Get(anIndex[0], anIndex[2], anIndex[1]); + Standard_Integer aDegenInTri = findDegenNodeInTri(anEdgePoly, anIndex); + if (aDegenInTri != -1) + { + ++aNbDupNodes; + } + } + } } } + aNbVertices += aNbDupNodes; if (aNbVertices < 3 || aNbTriangles <= 0) { return Handle(Graphic3d_ArrayOfTriangles)(); @@ -192,29 +267,6 @@ namespace } const Standard_Integer aDecal = anArray->VertexNumber(); - //check for duplicated vertices in the same face and average the normals - //to remove potential bad seams - for (Standard_Integer aNodeIter = 1; aNodeIter <= aT->NbNodes(); ++aNodeIter) - { - aPoint = aT->Node(aNodeIter); - gp_Dir aNorm = aT->Normal(aNodeIter); - for (Standard_Integer aSeekPtr = aNodeIter - 1; aSeekPtr > 0; --aSeekPtr) - { - gp_Pnt aMatchPnt = aT->Node(aSeekPtr); - gp_Dir aMatchNormal = aT->Normal(aSeekPtr); - if (aMatchPnt.Distance(aPoint) < Precision::Confusion()) - { - gp_Vec aAuxVec((aNorm.X() + aMatchNormal.X()) * 0.5, - (aNorm.Y() + aMatchNormal.Y()) * 0.5, - (aNorm.Z() + aMatchNormal.Z()) * 0.5); - aAuxVec.Normalize(); - gp_Dir aNewNormal(aAuxVec.X(), aAuxVec.Y(), aAuxVec.Z()); - aT->SetNormal(aNodeIter, aNewNormal); - aT->SetNormal(aSeekPtr, aNewNormal); - } - } - } - for (Standard_Integer aNodeIter = 1; aNodeIter <= aT->NbNodes(); ++aNodeIter) { aPoint = aT->Node (aNodeIter); @@ -245,7 +297,26 @@ namespace } // Fill array with vertex and edge visibility info - Standard_Integer anIndex[3]; + //Standard_Integer anIndex[3]; + + // handle degenerated nodes + NCollection_Sequence aDegenPolygons; + if (aNbDupNodes > 0) + { + for (TopExp_Explorer anEdgeIt(aFace, TopAbs_EDGE); anEdgeIt.More(); anEdgeIt.Next()) + { + const TopoDS_Edge& anEdge = TopoDS::Edge(anEdgeIt.Current()); + if (BRep_Tool::Degenerated(anEdge)) + { + Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(anEdge, aT, aLocDummy); + if (!aPoly.IsNull()) + { + aDegenPolygons.Append(aPoly); + } + } + } + } + for (Standard_Integer aTriIter = 1; aTriIter <= aT->NbTriangles(); ++aTriIter) { if ((aFace.Orientation() == TopAbs_REVERSED)) @@ -279,12 +350,41 @@ namespace aV1.Normalize(); aV2.Normalize(); aV1.Cross (aV2); - if (aV1.SquareMagnitude() > aPreci) + //if (aV1.SquareMagnitude() > aPreci) + //{ + // anArray->AddEdges (anIndex[0] + aDecal, + // anIndex[1] + aDecal, + // anIndex[2] + aDecal); + //} + if (aV1.SquareMagnitude() <= aPreci) { - anArray->AddEdges (anIndex[0] + aDecal, - anIndex[1] + aDecal, - anIndex[2] + aDecal); + continue; } + // duplicate degenerated node using normal to the triangle + const Standard_Integer aDegenInTri = !aDegenPolygons.IsEmpty() + ? findDegenNodeInTri(aDegenPolygons, anIndex) + : -1; + if (aDegenInTri != -1) + { + gp_Pnt aNewPoint = aT->Node(anIndex[aDegenInTri]); + if (theHasTexels && aT->HasUVNodes()) + { + const gp_Pnt2d aNode2d = aT->UVNode(anIndex[aDegenInTri]); + const gp_Pnt2d aTexel = (dUmax == 0.0 || dVmax == 0.0) + ? aNode2d + : gp_Pnt2d((-theUVOrigin.X() + (theUVRepeat.X() * (aNode2d.X() - aUmin)) / dUmax) / theUVScale.X(), + (-theUVOrigin.Y() + (theUVRepeat.Y() * (aNode2d.Y() - aVmin)) / dVmax) / theUVScale.Y()); + anIndex[aDegenInTri] = anArray->AddVertex(aNewPoint, aV1, aTexel) - aDecal; + } + else + { + anIndex[aDegenInTri] = anArray->AddVertex(aNewPoint, aV1) - aDecal; + } + } + + anArray->AddEdge(anIndex[0] + aDecal); + anArray->AddEdge(anIndex[1] + aDecal); + anArray->AddEdge(anIndex[2] + aDecal); } } return anArray;