0024282: Shaded presentation is not computed due to exception in StdPrs_ToolShadedSha...
authorkgv <kgv@opencascade.com>
Thu, 31 Oct 2013 09:28:33 +0000 (13:28 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 31 Oct 2013 09:30:01 +0000 (13:30 +0400)
Fix gp_Dir initialization with zero modulus
StdPrs_ToolShadedShape::Normal() - reduce code duplication
Test cases for issue CR24282

src/StdPrs/StdPrs_ToolShadedShape.cxx
tests/bugs/vis/bug24282 [new file with mode: 0644]

index 5f16bf6..8ace9ac 100755 (executable)
 // purpose or non-infringement. Please see the License for the specific terms
 // and conditions governing the rights and limitations under the License.
 
-
-
 #include <StdPrs_ToolShadedShape.ixx>
+
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <GeomAbs_SurfaceType.hxx>
+#include <GeomLib.hxx>
+#include <gp_Vec.hxx>
+#include <Poly_Connect.hxx>
 #include <Poly_Triangulation.hxx>
+#include <Precision.hxx>
 #include <TColgp_HArray1OfPnt.hxx>
 #include <TColgp_Array1OfPnt.hxx>
 #include <TColgp_Array1OfPnt2d.hxx>
-#include <Poly_Connect.hxx>
 #include <TopAbs_Orientation.hxx>
-#include <GeomAbs_SurfaceType.hxx>
-//#include <CSLib.hxx>
-#include <GeomLib.hxx>
-#include <gp_Vec.hxx>
-#include <Precision.hxx>
-#include <BRepAdaptor_Surface.hxx>
-#include <BRep_Tool.hxx>
 #include <TopLoc_Location.hxx>
 #include <TShort_HArray1OfShortReal.hxx>
 #include <TShort_Array1OfShortReal.hxx>
 
 //=======================================================================
 //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 (file)
index 0000000..832faa6
--- /dev/null
@@ -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