From 9447f912580295d718b6491a698cac7b932825b3 Mon Sep 17 00:00:00 2001 From: kgv Date: Thu, 31 Oct 2013 13:28:33 +0400 Subject: [PATCH] 0024282: Shaded presentation is not computed due to exception in StdPrs_ToolShadedShape::Normal() Fix gp_Dir initialization with zero modulus StdPrs_ToolShadedShape::Normal() - reduce code duplication Test cases for issue CR24282 --- src/StdPrs/StdPrs_ToolShadedShape.cxx | 215 ++++++++++---------------- tests/bugs/vis/bug24282 | 19 +++ 2 files changed, 99 insertions(+), 135 deletions(-) create mode 100644 tests/bugs/vis/bug24282 diff --git a/src/StdPrs/StdPrs_ToolShadedShape.cxx b/src/StdPrs/StdPrs_ToolShadedShape.cxx index 5f16bf6f11..8ace9ac768 100755 --- a/src/StdPrs/StdPrs_ToolShadedShape.cxx +++ b/src/StdPrs/StdPrs_ToolShadedShape.cxx @@ -18,178 +18,123 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - - #include + +#include +#include +#include +#include +#include +#include #include +#include #include #include #include -#include #include -#include -//#include -#include -#include -#include -#include -#include #include #include #include //======================================================================= //function : IsClosed -//purpose : +//purpose : //======================================================================= - -Standard_Boolean StdPrs_ToolShadedShape::IsClosed(const TopoDS_Shape& aShape) +Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape) { - return aShape.Closed(); + return theShape.Closed(); } - //======================================================================= //function : Triangulation -//purpose : +//purpose : //======================================================================= - -Handle(Poly_Triangulation) StdPrs_ToolShadedShape::Triangulation - (const TopoDS_Face& aFace, - TopLoc_Location& loc) +Handle(Poly_Triangulation) StdPrs_ToolShadedShape::Triangulation (const TopoDS_Face& theFace, + TopLoc_Location& theLoc) { - return BRep_Tool::Triangulation(aFace, loc); + return BRep_Tool::Triangulation (theFace, theLoc); } - //======================================================================= //function : Normal -//purpose : +//purpose : //======================================================================= - -void StdPrs_ToolShadedShape::Normal(const TopoDS_Face& aFace, - Poly_Connect& pc, - TColgp_Array1OfDir& Nor) +void StdPrs_ToolShadedShape::Normal (const TopoDS_Face& theFace, + Poly_Connect& thePolyConnect, + TColgp_Array1OfDir& theNormals) { - const Handle(Poly_Triangulation)& T = pc.Triangulation(); - BRepAdaptor_Surface S; - Standard_Boolean hasUV = T->HasUVNodes(); - Standard_Integer i; - TopLoc_Location l; - // move to zero - TopoDS_Face zeroFace = TopoDS::Face(aFace.Located(TopLoc_Location())); - //take in face the surface location - - //Handle(Geom_Surface) GS = BRep_Tool::Surface(aFace, l); - Handle(Geom_Surface) GS = BRep_Tool::Surface(zeroFace); - - if(T->HasNormals()) { - const TColgp_Array1OfPnt& Nodes = T->Nodes(); - const TShort_Array1OfShortReal& Normals = T->Normals(); - const Standard_ShortReal * arrN = &(Normals.Value(Normals.Lower())); - for( i = Nodes.Lower(); i <= Nodes.Upper(); i++) { - Standard_Integer in = 3*(i-Nodes.Lower()); - gp_Dir N(arrN[in + 0], arrN[in + 1], arrN[in + 2]); - Nor(i) = N; + const Handle(Poly_Triangulation)& aPolyTri = thePolyConnect.Triangulation(); + const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes(); + if (aPolyTri->HasNormals()) + { + // normals pre-computed in triangulation structure + const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals(); + const Standard_ShortReal* aNormArr = &(aNormals.Value (aNormals.Lower())); + for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower()); + const gp_Dir aNorm (aNormArr[anId + 0], + aNormArr[anId + 1], + aNormArr[anId + 2]); + theNormals (aNodeIter) = aNorm; } - if (aFace.Orientation() == TopAbs_REVERSED) { - for( i = Nodes.Lower(); i <= Nodes.Upper(); i++) { - Nor.ChangeValue(i).Reverse(); + if (theFace.Orientation() == TopAbs_REVERSED) + { + for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue (aNodeIter).Reverse(); } } - - + return; } - else if (hasUV && !GS.IsNull()) { - Standard_Integer nbNormVal = T->NbNodes() * 3; - Handle(TShort_HArray1OfShortReal) Normals = - new TShort_HArray1OfShortReal(1, nbNormVal); - - const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes(); - Standard_Real Tol = Precision::Confusion(); - for (i = UVNodes.Lower(); i <= UVNodes.Upper(); i++) { - - if(GeomLib::NormEstim(GS, UVNodes(i), Tol, Nor(i)) > 1) { - const TColgp_Array1OfPnt& Nodes = T->Nodes(); - Standard_Integer n[3]; - const Poly_Array1OfTriangle& triangles = T->Triangles(); - - gp_XYZ eqPlan(0, 0, 0); - - Standard_Real modmax = 0.; - for (pc.Initialize(i); pc.More(); pc.Next()) { - triangles(pc.Value()).Get(n[0], n[1], n[2]); - gp_XYZ v1(Nodes(n[1]).Coord()-Nodes(n[0]).Coord()); - gp_XYZ v2(Nodes(n[2]).Coord()-Nodes(n[1]).Coord()); - gp_XYZ vv = v1^v2; - Standard_Real mod = vv.Modulus(); - - if(mod < Tol) continue; - - eqPlan += vv/mod; - } - - modmax = eqPlan.Modulus(); - if(modmax > Tol) Nor(i) = gp_Dir(eqPlan); - else Nor(i) = gp_Dir(0., 0., 1.); + // take in face the surface location + const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location())); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace); + const Standard_Real aTol = Precision::Confusion(); + Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aPolyTri->NbNodes() * 3); + const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles(); + const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull() + ? &aPolyTri->UVNodes() + : NULL; + Standard_Integer aTri[3]; + for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + // try to retrieve normal from real surface first, when UV coordinates are available + if (aNodesUV == NULL + || GeomLib::NormEstim (aSurf, aNodesUV->Value (aNodeIter), aTol, theNormals (aNodeIter)) > 1) + { + // compute flat normals + gp_XYZ eqPlan (0.0, 0.0, 0.0); + for (thePolyConnect.Initialize (aNodeIter); thePolyConnect.More(); thePolyConnect.Next()) + { + aTriangles (thePolyConnect.Value()).Get (aTri[0], aTri[1], aTri[2]); + const gp_XYZ v1 (aNodes (aTri[1]).Coord() - aNodes (aTri[0]).Coord()); + const gp_XYZ v2 (aNodes (aTri[2]).Coord() - aNodes (aTri[1]).Coord()); + const gp_XYZ vv = v1 ^ v2; + const Standard_Real aMod = vv.Modulus(); + if (aMod >= aTol) + { + eqPlan += vv / aMod; + } } - - Standard_Integer j = (i - UVNodes.Lower()) * 3; - Normals->SetValue(j + 1, (Standard_ShortReal)Nor(i).X()); - Normals->SetValue(j + 2, (Standard_ShortReal)Nor(i).Y()); - Normals->SetValue(j + 3, (Standard_ShortReal)Nor(i).Z()); - - if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse(); - + const Standard_Real aModMax = eqPlan.Modulus(); + theNormals (aNodeIter) = (aModMax > aTol) ? gp_Dir (eqPlan) : gp::DZ(); } - T->SetNormals(Normals); + const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3; + aNormals->SetValue (anId + 1, (Standard_ShortReal )theNormals (aNodeIter).X()); + aNormals->SetValue (anId + 2, (Standard_ShortReal )theNormals (aNodeIter).Y()); + aNormals->SetValue (anId + 3, (Standard_ShortReal )theNormals (aNodeIter).Z()); } - else { - Standard_Integer nbNormVal = T->NbNodes() * 3; - Handle(TShort_HArray1OfShortReal) Normals = - new TShort_HArray1OfShortReal(1, nbNormVal); - - const TColgp_Array1OfPnt& Nodes = T->Nodes(); - Standard_Integer n[3]; - const Poly_Array1OfTriangle& triangles = T->Triangles(); - Standard_Real Tol = Precision::Confusion(); - - for (i = Nodes.Lower(); i <= Nodes.Upper(); i++) { - gp_XYZ eqPlan(0, 0, 0); - for (pc.Initialize(i); pc.More(); pc.Next()) { - triangles(pc.Value()).Get(n[0], n[1], n[2]); - gp_XYZ v1(Nodes(n[1]).Coord()-Nodes(n[0]).Coord()); - gp_XYZ v2(Nodes(n[2]).Coord()-Nodes(n[1]).Coord()); - gp_XYZ vv = v1^v2; - Standard_Real mod = vv.Modulus(); - - if(mod < Tol) continue; - - eqPlan += vv/mod; - } - - Standard_Real modmax = eqPlan.Modulus(); - - if(modmax > Tol) Nor(i) = gp_Dir(eqPlan); - else Nor(i) = gp_Dir(0., 0., 1.); - - Nor(i) = gp_Dir(eqPlan); - - Standard_Integer j = (i - Nodes.Lower()) * 3; - Normals->SetValue(j + 1, (Standard_ShortReal)Nor(i).X()); - Normals->SetValue(j + 2, (Standard_ShortReal)Nor(i).Y()); - Normals->SetValue(j + 3, (Standard_ShortReal)Nor(i).Z()); - - if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse(); + aPolyTri->SetNormals (aNormals); + if (theFace.Orientation() == TopAbs_REVERSED) + { + for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter) + { + theNormals.ChangeValue (aNodeIter).Reverse(); } - - T->SetNormals(Normals); } - - } - diff --git a/tests/bugs/vis/bug24282 b/tests/bugs/vis/bug24282 new file mode 100644 index 0000000000..832faa6a39 --- /dev/null +++ b/tests/bugs/vis/bug24282 @@ -0,0 +1,19 @@ +puts "========" +puts "OCC24282" +#puts "Shaded presentation is not computed due to exception in StdPrs_ToolShadedShape::Normal()" +puts "========" + +restore [locate_data_file bug24282_box_no_uv.brep] b +vinit +vdisplay b +vfit +vsetdispmode b 1 + +set x_coord 200 +set y_coord 200 +set RED 0.78039216995239258 +set GREEN 0.55294120311737061 +set BLUE 0.094117648899555206 +checkcolor ${x_coord} ${y_coord} ${RED} ${GREEN} ${BLUE} + +set only_screen 1