From fcc61cc4c96d3c38025ce7e14b0e965b4afb342a Mon Sep 17 00:00:00 2001 From: vro Date: Thu, 30 Oct 2014 12:18:22 +0300 Subject: [PATCH] 0025405: STL reader doesn't keep shared nodes 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 --- .../BRepBuilderAPI_VertexInspector.hxx | 7 ++- src/RWStl/RWStl.cxx | 54 ++++++++++++++++--- src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx | 33 ++++++++++++ tests/bugs/vis/bug10702 | 3 +- tests/bugs/xde/bug25405 | 25 +++++++++ 5 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 tests/bugs/xde/bug25405 diff --git a/src/BRepBuilderAPI/BRepBuilderAPI_VertexInspector.hxx b/src/BRepBuilderAPI/BRepBuilderAPI_VertexInspector.hxx index d52372625b..486d913e50 100644 --- a/src/BRepBuilderAPI/BRepBuilderAPI_VertexInspector.hxx +++ b/src/BRepBuilderAPI/BRepBuilderAPI_VertexInspector.hxx @@ -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; diff --git a/src/RWStl/RWStl.cxx b/src/RWStl/RWStl.cxx index bd3be1ce8e..4346f27e7c 100644 --- a/src/RWStl/RWStl.cxx +++ b/src/RWStl/RWStl.cxx @@ -30,6 +30,35 @@ #include #include +#include +#include + +// 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" diff --git a/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx b/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx index 6ec784a1f1..e13d560005 100644 --- a/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx +++ b/src/XSDRAWSTLVRML/XSDRAWSTLVRML.cxx @@ -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 ); } //============================================================================== diff --git a/tests/bugs/vis/bug10702 b/tests/bugs/vis/bug10702 index 64db0ba304..0597d63b02 100755 --- a/tests/bugs/vis/bug10702 +++ b/tests/bugs/vis/bug10702 @@ -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 index 0000000000..08e9c9037d --- /dev/null +++ b/tests/bugs/xde/bug25405 @@ -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