0025405: STL reader doesn't keep shared nodes
authorvro <vro@opencascade.com>
Thu, 30 Oct 2014 09:18:22 +0000 (12:18 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 30 Oct 2014 09:19:36 +0000 (12:19 +0300)
An improved RWSTL::ReadFile() method + a draw-command returning the number of nodes and triangles for a MeshVS_Mesh object based on STL mesh data source.

An indexed map of points is replaced by a CellFilter of XYZ objects already implemented in BRepBuilderAPI.
Also, BRepBuilderAPI_VertexInspector became exported for TKTopAlgo library (Standard_EXPORT is added for the methods of this class).

Standard_EXPORT is removed for in-line methods of BRepBuilderAPI_VertexInspector

Test-case for issue #25405

Update of test-cases, according to new behavior

src/BRepBuilderAPI/BRepBuilderAPI_VertexInspector.hxx
src/RWStl/RWStl.cxx
src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx
tests/bugs/vis/bug10702
tests/bugs/xde/bug25405 [new file with mode: 0644]

index d523726..486d913 100644 (file)
@@ -37,8 +37,7 @@ class BRepBuilderAPI_VertexInspector : public NCollection_CellFilter_InspectorXY
 public:
   typedef Standard_Integer Target;
   //! Constructor; remembers the tolerance
-  BRepBuilderAPI_VertexInspector (const Standard_Real theTol)
-                                  : myTol(theTol*theTol)
+  BRepBuilderAPI_VertexInspector (const Standard_Real theTol):myTol(theTol*theTol)
   {}
 
   //! Keep the points used for comparison
@@ -54,7 +53,7 @@ public:
   }
   
   //! Set current point to search for coincidence
-  void SetCurrent (const gp_XYZ& theCurPnt) 
+  void SetCurrent (const gp_XYZ& theCurPnt)
   { 
     myCurrent = theCurPnt;
   }
@@ -66,7 +65,7 @@ public:
   }
 
   //! Implementation of inspection method
-  NCollection_CellFilter_Action Inspect (const Standard_Integer theTarget); 
+  Standard_EXPORT NCollection_CellFilter_Action Inspect (const Standard_Integer theTarget); 
 
 private:
   Standard_Real myTol;
index bd3be1c..4346f27 100644 (file)
 #include <stdio.h>
 #include <gp_Vec.hxx>
 
+#include <BRepBuilderAPI_CellFilter.hxx>
+#include <BRepBuilderAPI_VertexInspector.hxx>
+
+// A static method adding nodes to a mesh and keeping coincident (sharing) nodes.
+static Standard_Integer AddVertex(Handle(StlMesh_Mesh)& mesh,
+                                  BRepBuilderAPI_CellFilter& filter, 
+                                  BRepBuilderAPI_VertexInspector& inspector,
+                                  const gp_XYZ& p)
+{
+  Standard_Integer index;
+  inspector.SetCurrent(p);
+  gp_XYZ minp = inspector.Shift(p, -Precision::Confusion());
+  gp_XYZ maxp = inspector.Shift(p, +Precision::Confusion());
+  filter.Inspect(minp, maxp, inspector);
+  const TColStd_ListOfInteger& indices = inspector.ResInd();
+  if (indices.IsEmpty() == Standard_False)
+  {
+    index = indices.First(); // it should be only one
+    inspector.ClearResList();
+  }
+  else
+  {
+    index = mesh->AddVertex(p.X(), p.Y(), p.Z());
+    filter.Add(index, p);
+    inspector.Add(p);
+  }
+  return index;
+}
+
 // constants
 static const size_t HEADER_SIZE           =  84;
 static const size_t SIZEOF_STL_FACET      =  50;
@@ -357,6 +386,10 @@ Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath,
   Handle(StlMesh_Mesh) ReadMesh = new StlMesh_Mesh ();
   ReadMesh->AddDomain ();
 
+  // Filter unique vertices to share the nodes of the mesh.
+  BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
+  BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
+  
   for (ifacet=1; ifacet<=NBFACET; ++ifacet) {
     // read normal coordinates
     fx = ReadFloat2Double(theFile);
@@ -378,9 +411,12 @@ Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath,
     fy3 = ReadFloat2Double(theFile);
     fz3 = ReadFloat2Double(theFile);
 
-    i1 = ReadMesh->AddOnlyNewVertex (fx1,fy1,fz1);
-    i2 = ReadMesh->AddOnlyNewVertex (fx2,fy2,fz2);
-    i3 = ReadMesh->AddOnlyNewVertex (fx3,fy3,fz3);
+    // Add vertices.
+    i1 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx1, fy1, fz1));
+    i2 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx2, fy2, fz2));
+    i3 = AddVertex(ReadMesh, uniqueVertices, inspector, gp_XYZ(fx3, fy3, fz3));
+
+    // Add triangle.
     ReadMesh->AddTriangle (i1,i2,i3,fx,fy,fz);
 
     // skip extra bytes
@@ -389,8 +425,8 @@ Handle(StlMesh_Mesh) RWStl::ReadBinary (const OSD_Path& thePath,
 
   theFile.Close ();
   return ReadMesh;
-
 }
+
 //=======================================================================
 //function : ReadAscii
 //Design   :
@@ -442,6 +478,10 @@ Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
   ReadMesh = new StlMesh_Mesh();
   ReadMesh->AddDomain();
 
+  // Filter unique vertices to share the nodes of the mesh.
+  BRepBuilderAPI_CellFilter uniqueVertices(Precision::Confusion());
+  BRepBuilderAPI_VertexInspector inspector(Precision::Confusion());
+  
   // main reading
   Message_ProgressSentry aPS (theProgInd, "Triangles", 0, (nbTris - 1) * 1.0 / IND_THRESHOLD, 1);
   for (iTri = 0; iTri < nbTris && aPS.More();)
@@ -469,9 +509,9 @@ Handle(StlMesh_Mesh) RWStl::ReadAscii (const OSD_Path& thePath,
 
     // here the facet must be built and put in the mesh datastructure
 
-    i1 = ReadMesh->AddOnlyNewVertex (aV1.X(), aV1.Y(), aV1.Z());
-    i2 = ReadMesh->AddOnlyNewVertex (aV2.X(), aV2.Y(), aV2.Z());
-    i3 = ReadMesh->AddOnlyNewVertex (aV3.X(), aV3.Y(), aV3.Z());
+    i1 = AddVertex(ReadMesh, uniqueVertices, inspector, aV1);
+    i2 = AddVertex(ReadMesh, uniqueVertices, inspector, aV2);
+    i3 = AddVertex(ReadMesh, uniqueVertices, inspector, aV3);
     ReadMesh->AddTriangle (i1, i2, i3, aN.X(), aN.Y(), aN.Z());
 
     // skip the keywords "endloop"
index 6ec784a..e13d560 100644 (file)
@@ -1185,6 +1185,38 @@ static Standard_Integer tovrml(Draw_Interpretor& di, Standard_Integer argc, cons
 
 //-----------------------------------------------------------------------------
 
+static Standard_Integer meshinfo(Draw_Interpretor& di,
+                                 Standard_Integer argc,
+                                 const char** argv)
+{
+  if ( argc != 2 )
+  {
+    di << "Wrong number of parameters. Use : meshinfo mesh" << "\n";
+    return 0;
+  }
+
+  Handle(MeshVS_Mesh) aMesh = getMesh(argv[ 1 ], di);
+  if ( aMesh.IsNull() )
+  {
+    di << "Mesh not found" << "\n";
+    return 0;
+  }
+
+  Handle(XSDRAWSTLVRML_DataSource) stlMeshSource = Handle(XSDRAWSTLVRML_DataSource)::DownCast(aMesh->GetDataSource());
+  if (!stlMeshSource.IsNull())
+  {
+    const TColStd_PackedMapOfInteger& nodes = stlMeshSource->GetAllNodes();
+    const TColStd_PackedMapOfInteger& tris  = stlMeshSource->GetAllElements();
+
+    di << "Nb nodes = " << nodes.Extent() << "\n";
+    di << "Nb triangles = " << tris.Extent() << "\n";
+  }
+
+  return 0;
+}
+
+//-----------------------------------------------------------------------------
+
 void  XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
 {
   const char* g = "XSTEP-STL/VRML";  // Step transfer file commands
@@ -1213,6 +1245,7 @@ void  XSDRAWSTLVRML::InitCommands (Draw_Interpretor& theCommands)
   theCommands.Add ("meshtext",        "display text labels",                          __FILE__, meshtext,        g );
   theCommands.Add ("meshdeform",      "display deformed mesh",                        __FILE__, meshdeform,      g );
   theCommands.Add ("mesh_edge_width", "set width of edges",                           __FILE__, mesh_edge_width, g );
+  theCommands.Add ("meshinfo",        "displays the number of nodes and triangles",   __FILE__, meshinfo,        g );
 }
 
 //==============================================================================
index 64db0ba..0597d63 100755 (executable)
@@ -36,7 +36,8 @@ checkcolor $x_coord $y_coord 0 0 0.36
 meshcolors m nodal 0
 puts "\nDisplay nodal color presentation"
 
-checkcolor $x_coord $y_coord 0.46 0.12 0.37
+#checkcolor $x_coord $y_coord 0.46 0.12 0.37
+checkcolor $x_coord $y_coord 0.72 0.72 0.70
 
 set only_screen 1
 
diff --git a/tests/bugs/xde/bug25405 b/tests/bugs/xde/bug25405
new file mode 100644 (file)
index 0000000..08e9c90
--- /dev/null
@@ -0,0 +1,25 @@
+puts "========"
+puts "OCC25405"
+puts "========"
+puts ""
+########################################
+# STL reader doesn't keep shared nodes
+########################################
+
+set GoodNodesNB 64215
+set GoodTrianglesNB 117694
+
+vinit
+
+meshfromstl s [locate_data_file head.stl]
+set bug_info [meshinfo s]
+
+if {$GoodNodesNB != [lindex $bug_info 3]} {
+  puts "ERROR: Number of nodes is incorrect: [lindex $bug_info 3] (should be $GoodNodesNB)"
+}
+
+if {$GoodTrianglesNB != [lindex $bug_info 7]} {
+  puts "ERROR: Number of triangles is incorrect: [lindex $bug_info 7] (should be $GoodTrianglesNB)"
+}
+
+set only_screen 1