diff --git a/benchmarks/benchmark_opencascade/main.cpp b/benchmarks/benchmark_opencascade/main.cpp index 095bf90..e7cfd03 100644 --- a/benchmarks/benchmark_opencascade/main.cpp +++ b/benchmarks/benchmark_opencascade/main.cpp @@ -61,7 +61,7 @@ static void stl_read(const void* filepath) stlMesh = new StlMesh_Mesh; const int error = gmio_stl_read_file( static_cast(filepath), - gmio_stl_hnd_occmesh_creator(stlMesh), + gmio_stl_occmesh_creator(stlMesh), NULL); if (error != GMIO_ERROR_OK) printf("gmio error: 0x%X\n", error); @@ -69,7 +69,6 @@ static void stl_read(const void* filepath) static void stl_write(const char* filepath, gmio_stl_format format) { - const gmio_occ_stl_mesh_domain occ_mesh_domain(stlMesh); gmio_stl_write_options options = {}; options.stla_float32_format = GMIO_FLOAT_TEXT_FORMAT_SHORTEST_UPPERCASE; options.stla_float32_prec = 7; @@ -77,7 +76,7 @@ static void stl_write(const char* filepath, gmio_stl_format format) gmio_stl_write_file( format, static_cast(filepath), - gmio_stl_occmesh(&occ_mesh_domain), + gmio_stl_occmesh(stlMesh), &options); if (error != GMIO_ERROR_OK) printf("gmio error: 0x%X\n", error); diff --git a/src/gmio_support/stl_occ.cpp b/src/gmio_support/stl_occ.cpp index 8e6b0e6..8d5276a 100644 --- a/src/gmio_support/stl_occ.cpp +++ b/src/gmio_support/stl_occ.cpp @@ -31,7 +31,7 @@ static StlMesh_Mesh* occMeshPtr(const Handle_StlMesh_Mesh& mesh) } static void occmesh_add_triangle( - void* cookie, uint32_t tri_id, const struct gmio_stl_triangle* tri) + void* cookie, uint32_t tri_id, const gmio_stl_triangle* tri) { StlMesh_Mesh* mesh = static_cast(cookie); if (tri_id == 0) @@ -46,94 +46,113 @@ static void occmesh_add_triangle( n.x, n.y, n.z); } -static void occmesh_get_triangle( - const void* cookie, uint32_t tri_id, struct gmio_stl_triangle* tri) +static inline void gmio_stl_occ_copy_xyz( + gmio_stl_coords* stl_coords, const gp_XYZ& coords) { - const struct gmio_occ_stl_mesh_domain* mesh_domain = - static_cast(cookie); - const Handle_StlMesh_MeshTriangle& occTri = - mesh_domain->triangles()->Value(tri_id + 1); - int idV1; - int idV2; - int idV3; - double xN; - double yN; - double zN; - occTri->GetVertexAndOrientation(idV1, idV2, idV3, xN, yN, zN); - gmio_stl_coords& n = tri->n; - n.x = static_cast(xN); - n.y = static_cast(yN); - n.z = static_cast(zN); + stl_coords->x = static_cast(coords.X()); + stl_coords->y = static_cast(coords.Y()); + stl_coords->z = static_cast(coords.Z()); +} - const TColgp_SequenceOfXYZ& vertices = *mesh_domain->vertices(); - const gp_XYZ& coordsV1 = vertices.Value(idV1); - gmio_stl_coords& v1 = tri->v1; - v1.x = static_cast(coordsV1.X()); - v1.y = static_cast(coordsV1.Y()); - v1.z = static_cast(coordsV1.Z()); +static void occmesh_get_triangle( + const void* cookie, uint32_t tri_id, gmio_stl_triangle* tri) +{ + void* wcookie = const_cast(cookie); + gmio_stl_occmesh_iterator* it = + static_cast(wcookie); - const gp_XYZ& coordsV2 = vertices.Value(idV2); - gmio_stl_coords& v2 = tri->v2; - v2.x = static_cast(coordsV2.X()); - v2.y = static_cast(coordsV2.Y()); - v2.z = static_cast(coordsV2.Z()); + if (it->move_to_next_tri(tri_id)) { + const Handle_StlMesh_MeshTriangle& occTri = it->domain_tri(tri_id); + int idV1, idV2, idV3; + double xN, yN, zN; + occTri->GetVertexAndOrientation(idV1, idV2, idV3, xN, yN, zN); + gmio_stl_coords& n = tri->n; + n.x = static_cast(xN); + n.y = static_cast(yN); + n.z = static_cast(zN); - const gp_XYZ& coordsV3 = vertices.Value(idV3); - gmio_stl_coords& v3 = tri->v3; - v3.x = static_cast(coordsV3.X()); - v3.y = static_cast(coordsV3.Y()); - v3.z = static_cast(coordsV3.Z()); + const TColgp_SequenceOfXYZ& vertices = it->domain_vertices(); + gmio_stl_occ_copy_xyz(&tri->v1, vertices.Value(idV1)); + gmio_stl_occ_copy_xyz(&tri->v2, vertices.Value(idV2)); + gmio_stl_occ_copy_xyz(&tri->v3, vertices.Value(idV3)); + } } } // namespace internal -struct gmio_stl_mesh gmio_stl_occmesh(const struct gmio_occ_stl_mesh_domain* mesh_domain) +gmio_stl_mesh gmio_stl_occmesh(const gmio_stl_occmesh_iterator& it) { - struct gmio_stl_mesh mesh = {0}; - mesh.cookie = mesh_domain; - if (mesh_domain != NULL && mesh_domain->mesh() != NULL) { - mesh.triangle_count = - mesh_domain->mesh()->NbTriangles(mesh_domain->domain_id()); - } + gmio_stl_mesh mesh = {}; + mesh.cookie = ⁢ + const int domain_count = it.mesh()->NbDomains(); + for (int dom_id = 1; dom_id <= domain_count; ++dom_id) + mesh.triangle_count += it.mesh()->NbTriangles(dom_id); mesh.func_get_triangle = internal::occmesh_get_triangle; return mesh; } -struct gmio_stl_mesh_creator gmio_stl_occmesh_creator(StlMesh_Mesh* mesh) +gmio_stl_mesh_creator gmio_stl_occmesh_creator(StlMesh_Mesh* mesh) { - struct gmio_stl_mesh_creator creator = {0}; + gmio_stl_mesh_creator creator = {}; creator.cookie = mesh; creator.func_add_triangle = internal::occmesh_add_triangle; return creator; } -struct gmio_stl_mesh_creator gmio_stl_hnd_occmesh_creator(const Handle_StlMesh_Mesh &hnd) +gmio_stl_mesh_creator gmio_stl_occmesh_creator(const Handle_StlMesh_Mesh &hnd) { return gmio_stl_occmesh_creator(internal::occMeshPtr(hnd)); } -gmio_occ_stl_mesh_domain::gmio_occ_stl_mesh_domain() - : m_mesh(NULL), - m_domain_id(0), - m_triangles(NULL), - m_vertices(NULL) +gmio_stl_occmesh_iterator::gmio_stl_occmesh_iterator() { + this->init(NULL); } -gmio_occ_stl_mesh_domain::gmio_occ_stl_mesh_domain( - const StlMesh_Mesh *msh, int dom_id) - : m_mesh(msh), - m_domain_id(dom_id), - m_triangles(&msh->Triangles(dom_id)), - m_vertices(&msh->Vertices(dom_id)) +gmio_stl_occmesh_iterator::gmio_stl_occmesh_iterator(const StlMesh_Mesh *mesh) { + this->init(mesh); } -gmio_occ_stl_mesh_domain::gmio_occ_stl_mesh_domain( - const Handle_StlMesh_Mesh &hnd, int dom_id) - : m_mesh(internal::occMeshPtr(hnd)), - m_domain_id(dom_id), - m_triangles(&m_mesh->Triangles(dom_id)), - m_vertices(&m_mesh->Vertices(dom_id)) +gmio_stl_occmesh_iterator::gmio_stl_occmesh_iterator(const Handle_StlMesh_Mesh &hnd) { + this->init(internal::occMeshPtr(hnd)); +} + +void gmio_stl_occmesh_iterator::init(const StlMesh_Mesh* mesh) +{ + m_mesh = mesh; + m_domain_id = 0; + m_domain_count = m_mesh != NULL ? m_mesh->NbDomains() : 0; + m_domain_triangles = NULL; + m_domain_vertices = NULL; + m_domain_first_tri_id = 0; + m_domain_last_tri_id = 0; + if (m_domain_count > 0) + this->cache_domain(1); +} + +void gmio_stl_occmesh_iterator::cache_domain(int dom_id) +{ + m_domain_id = dom_id; + m_domain_triangles = &m_mesh->Triangles(dom_id); + m_domain_vertices = &m_mesh->Vertices(dom_id); + const int dom_tricnt = m_domain_triangles->Length(); + m_domain_first_tri_id = + dom_tricnt > 0 ? m_domain_last_tri_id : m_domain_first_tri_id; + m_domain_last_tri_id += + dom_tricnt > 0 ? dom_tricnt - 1 : 0; +} + +bool gmio_stl_occmesh_iterator::move_to_next_tri(uint32_t tri_id) +{ + if (tri_id > m_domain_last_tri_id) { + if (m_domain_id < m_domain_count) { + ++m_domain_id; + this->cache_domain(m_domain_id); + return true; + } + return false; + } + return true; } diff --git a/src/gmio_support/stl_occ.h b/src/gmio_support/stl_occ.h index 9016091..1666d1c 100644 --- a/src/gmio_support/stl_occ.h +++ b/src/gmio_support/stl_occ.h @@ -31,39 +31,70 @@ #include "../gmio_stl/stl_mesh.h" #include "../gmio_stl/stl_mesh_creator.h" +#include + class Handle_StlMesh_Mesh; class StlMesh_Mesh; -class StlMesh_SequenceOfMeshTriangle; +class Handle_StlMesh_MeshTriangle; class TColgp_SequenceOfXYZ; -/*! Domain in a OpenCascade \c StlMesh_Mesh object +/*! Forward iterator over the triangles of OpenCascade's StlMesh_Mesh * - * The domain is indicated with its index within the STL mesh + * It is used to iterate efficiently over the triangles of all domains within + * a StlMesh_Mesh object. + * + * You don't have to use API of this class, it's intended to gmio_stl_mesh() */ -struct GMIO_LIBSUPPORT_EXPORT gmio_occ_stl_mesh_domain +struct GMIO_LIBSUPPORT_EXPORT gmio_stl_occmesh_iterator { - gmio_occ_stl_mesh_domain(); - gmio_occ_stl_mesh_domain(const StlMesh_Mesh* mesh, int dom_id = 1); - gmio_occ_stl_mesh_domain(const Handle_StlMesh_Mesh& hnd, int dom_id = 1); + gmio_stl_occmesh_iterator(); + gmio_stl_occmesh_iterator(const StlMesh_Mesh* mesh); + gmio_stl_occmesh_iterator(const Handle_StlMesh_Mesh& hnd); + bool move_to_next_tri(uint32_t tri_id); + inline const Handle_StlMesh_MeshTriangle& domain_tri(uint32_t tri_id) const; + inline const TColgp_SequenceOfXYZ& domain_vertices() const; inline const StlMesh_Mesh* mesh() const; - inline int domain_id() const; - inline const StlMesh_SequenceOfMeshTriangle* triangles() const; - inline const TColgp_SequenceOfXYZ* vertices() const; private: + void init(const StlMesh_Mesh* mesh); + void cache_domain(int dom_id); + const StlMesh_Mesh* m_mesh; + int m_domain_count; int m_domain_id; - const StlMesh_SequenceOfMeshTriangle* m_triangles; - const TColgp_SequenceOfXYZ* m_vertices; + const StlMesh_SequenceOfMeshTriangle* m_domain_triangles; + const TColgp_SequenceOfXYZ* m_domain_vertices; + uint32_t m_domain_first_tri_id; + uint32_t m_domain_last_tri_id; }; -/*! Returns a gmio_stl_mesh mapped to domain in StlMesh_Mesh +/*! Returns a gmio_stl_mesh mapped to the OCC mesh in iterator \p it * - * The mesh's cookie will point to \p mesh_domain + * The mesh's cookie will point to \c &it so the lifescope of the corresponding + * object must be at least as longer as the returned gmio_stl_mesh. + * Example of use: + * \code + * Handle_StlMesh_Mesh occmesh = ...; + * gmio_stl_write_file( + * stl_format, + * filepath, + * gmio_stl_occmesh(occmesh), // Implicit temporary iterator + * &options); + * \endcode + * + * Dangerous use: + * \code + * Handle_StlMesh_Mesh occmesh = ...; + * const gmio_stl_mesh mesh = + * gmio_stl_occmesh(gmio_stl_occmesh_iterator(occmesh)); + * // At this point the iterator object is destroyed, mesh.cookie points to + * // some garbage. The following line may cause a crash. + * gmio_stl_write_file(stl_format, filepath, mesh, &options); + * \endcode */ GMIO_LIBSUPPORT_EXPORT -struct gmio_stl_mesh gmio_stl_occmesh(const struct gmio_occ_stl_mesh_domain* mesh_domain); +gmio_stl_mesh gmio_stl_occmesh(const gmio_stl_occmesh_iterator& it); /*! Returns a gmio_stl_mesh_creator that will build a new domain in a * StlMesh_Mesh object @@ -71,7 +102,7 @@ struct gmio_stl_mesh gmio_stl_occmesh(const struct gmio_occ_stl_mesh_domain* mes * The creator's cookie will point \p mesh */ GMIO_LIBSUPPORT_EXPORT -struct gmio_stl_mesh_creator gmio_stl_occmesh_creator(StlMesh_Mesh* mesh); +gmio_stl_mesh_creator gmio_stl_occmesh_creator(StlMesh_Mesh* mesh); /*! Same as gmio_stl_occmesh_creator(StlMesh_Mesh*) but takes a handle * @@ -79,25 +110,26 @@ struct gmio_stl_mesh_creator gmio_stl_occmesh_creator(StlMesh_Mesh* mesh); * handle \p hnd */ GMIO_LIBSUPPORT_EXPORT -struct gmio_stl_mesh_creator gmio_stl_hnd_occmesh_creator(const Handle_StlMesh_Mesh& hnd); +gmio_stl_mesh_creator gmio_stl_occmesh_creator(const Handle_StlMesh_Mesh& hnd); -// -- -// -- Implementation -// -- +/* + * Implementation + */ -const StlMesh_Mesh* gmio_occ_stl_mesh_domain::mesh() const +const Handle_StlMesh_MeshTriangle& +gmio_stl_occmesh_iterator::domain_tri(uint32_t tri_id) const +{ + const int dom_tri_id = tri_id - m_domain_first_tri_id + 1; + return m_domain_triangles->Value(dom_tri_id); +} + +const TColgp_SequenceOfXYZ &gmio_stl_occmesh_iterator::domain_vertices() const +{ return *m_domain_vertices; } + +const StlMesh_Mesh *gmio_stl_occmesh_iterator::mesh() const { return m_mesh; } -int gmio_occ_stl_mesh_domain::domain_id() const -{ return m_domain_id; } - -const StlMesh_SequenceOfMeshTriangle* gmio_occ_stl_mesh_domain::triangles() const -{ return m_triangles; } - -const TColgp_SequenceOfXYZ* gmio_occ_stl_mesh_domain::vertices() const -{ return m_vertices; } - #endif /* GMIO_SUPPORT_STL_OCC_H */ /*! @} */ diff --git a/tests/fake_support/main.cpp b/tests/fake_support/main.cpp index d8d463e..aff9b55 100644 --- a/tests/fake_support/main.cpp +++ b/tests/fake_support/main.cpp @@ -11,7 +11,7 @@ int main() { // OpenCascade Handle_StlMesh_Mesh stlMesh; - gmio_stl_hnd_occmesh_creator(stlMesh); + gmio_stl_occmesh_creator(stlMesh); // Qt QFile file; diff --git a/tests/fake_support/opencascade/StlMesh_Mesh.hxx b/tests/fake_support/opencascade/StlMesh_Mesh.hxx index b79bd6e..d34a046 100644 --- a/tests/fake_support/opencascade/StlMesh_Mesh.hxx +++ b/tests/fake_support/opencascade/StlMesh_Mesh.hxx @@ -23,7 +23,10 @@ public: const double /*X*/, const double /*Y*/, const double /*Z*/) { return -1; } - virtual int NbTriangles(const int DomainIndex) const + virtual int NbTriangles(const int /*DomainIndex*/) const + { return 0; } + + virtual int NbDomains() const { return 0; } virtual const StlMesh_SequenceOfMeshTriangle& Triangles( diff --git a/tests/fake_support/opencascade/StlMesh_SequenceOfMeshTriangle.hxx b/tests/fake_support/opencascade/StlMesh_SequenceOfMeshTriangle.hxx index 098d835..11e3358 100644 --- a/tests/fake_support/opencascade/StlMesh_SequenceOfMeshTriangle.hxx +++ b/tests/fake_support/opencascade/StlMesh_SequenceOfMeshTriangle.hxx @@ -11,6 +11,9 @@ public: static Handle_StlMesh_MeshTriangle meshTri; return meshTri; } + + int Length() const + { return 0; } }; #endif // _StlMesh_SequenceOfMeshTriangle_HeaderFile