diff --git a/sandboxes/its_neighbor_index/main.cpp b/sandboxes/its_neighbor_index/main.cpp index 0e89da831..2ae6f47cd 100644 --- a/sandboxes/its_neighbor_index/main.cpp +++ b/sandboxes/its_neighbor_index/main.cpp @@ -24,50 +24,71 @@ static MeasureResult measure_index(const indexed_triangle_set &its, IndexCreator { Benchmark b; - b.start(); - ItsNeighborsWrapper itsn{its, fn(its)}; - b.stop(); - MeasureResult r; - r.t_index_create = b.getElapsedSec(); + for (int i = 0; i < 10; ++i) { + b.start(); + ItsNeighborsWrapper itsn{its, fn(its)}; + b.stop(); - b.start(); - its_split(itsn); - b.stop(); + r.t_index_create += b.getElapsedSec(); - r.t_split = b.getElapsedSec(); + b.start(); + its_split(itsn); + b.stop(); + + r.t_split += b.getElapsedSec(); + } + + r.t_index_create /= 10; + r.t_split /= 10; return r; } -static TriangleMesh two_spheres(double detail) +static indexed_triangle_set two_spheres(double detail) { - TriangleMesh sphere1 = make_sphere(10., 2 * PI / detail), sphere2 = sphere1; + auto sphere1 = its_make_sphere(10., 2 * PI / detail), sphere2 = sphere1; - sphere1.translate(-5.f, 0.f, 0.f); - sphere2.translate( 5.f, 0.f, 0.f); + its_transform(sphere1, Transform3f{}.translate(Vec3f{-5.f, 0.f, 0.f})); + its_transform(sphere2, Transform3f{}.translate(Vec3f{5.f, 0.f, 0.f})); - sphere1.merge(sphere2); - sphere1.require_shared_vertices(); + its_merge(sphere1, sphere2); return sphere1; } -static const std::map ToMeasure = { - {"simple", make_cube(10., 10., 10.) }, - {"two_spheres", two_spheres(200.)}, - {"two_spheres_detail", two_spheres(360.)}, - {"two_spheres_high_detail", two_spheres(3600.)}, +static const std::map ToMeasure = { + {"simple", its_make_cube(10., 10., 10.) }, // this has 12 faces, 8 vertices + {"two_spheres_1x", two_spheres(60.)}, + {"two_spheres_2x", two_spheres(120.)}, + {"two_spheres_4x", two_spheres(240.)}, + {"two_spheres_8x", two_spheres(480.)}, }; static const auto IndexFunctions = std::make_tuple( - std::make_pair("tamas's unordered_map based", its_create_neighbors_index_1), - std::make_pair("vojta std::sort based", its_create_neighbors_index_2), - std::make_pair("vojta tbb::parallel_sort based", its_create_neighbors_index_3), - std::make_pair("filip's vertex->face based", its_create_neighbors_index_5), - std::make_pair("tamas's std::sort based", its_create_neighbors_index_6), - std::make_pair("tamas's tbb::parallel_sort based", its_create_neighbors_index_7), - std::make_pair("tamas's map based", its_create_neighbors_index_8) + std::make_pair("tamas's unordered_map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_1); }), + std::make_pair("vojta std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_2); }), + std::make_pair("vojta tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_3); }), + std::make_pair("filip's vertex->face based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_5); }), + std::make_pair("tamas's std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_6); }), + std::make_pair("tamas's tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_7); }), + std::make_pair("tamas's map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_8); }), + std::make_pair("TriangleMesh split", [](const auto &its) { + TriangleMesh m{its}; + + MeasureResult ret; + for (int i = 0; i < 10; ++i) { + Benchmark b; + b.start(); + m.repair(); + m.split(); + b.stop(); + ret.t_split += b.getElapsedSec(); + } + ret.t_split /= 10; + + return ret; + }) ); static constexpr size_t IndexFuncNum = std::tuple_size_v; @@ -85,13 +106,12 @@ int main(const int argc, const char * argv[]) auto &name = m.first; auto &mesh = m.second; libnest2d::opt::metaloop::apply([&mesh, &name, &results, &funcnames](int N, auto &e) { - MeasureResult r = measure_index(mesh.its, e.second); + MeasureResult r = e.second(mesh); funcnames[N] = e.first; results[name][N] = r; }, IndexFunctions); } - std::string outfilename = "out.csv"; std::fstream outfile; if (argc > 1) { diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 49242db7e..64d8a8e4b 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -968,20 +968,22 @@ Polygon its_convex_hull_2d_above(const indexed_triangle_set &its, const Transfor } // Generate the vertex list for a cube solid of arbitrary size in X/Y/Z. +indexed_triangle_set its_make_cube(double xd, double yd, double zd) +{ + auto x = float(xd), y = float(yd), z = float(zd); + indexed_triangle_set mesh; + mesh.vertices = {{x, y, 0}, {x, 0, 0}, {0, 0, 0}, {0, y, 0}, + {x, y, z}, {0, y, z}, {0, 0, z}, {x, 0, z}}; + mesh.indices = {{0, 1, 2}, {0, 2, 3}, {4, 5, 6}, {4, 6, 7}, + {0, 4, 7}, {0, 7, 1}, {1, 7, 6}, {1, 6, 2}, + {2, 6, 5}, {2, 5, 3}, {4, 0, 3}, {4, 3, 5}}; + + return mesh; +} + TriangleMesh make_cube(double x, double y, double z) { - TriangleMesh mesh( - { - {x, y, 0}, {x, 0, 0}, {0, 0, 0}, - {0, y, 0}, {x, y, z}, {0, y, z}, - {0, 0, z}, {x, 0, z} - }, - { - {0, 1, 2}, {0, 2, 3}, {4, 5, 6}, - {4, 6, 7}, {0, 4, 7}, {0, 7, 1}, - {1, 7, 6}, {1, 6, 2}, {2, 6, 5}, - {2, 5, 3}, {4, 0, 3}, {4, 3, 5} - }); + TriangleMesh mesh(its_make_cube(x, y, z)); mesh.repair(); return mesh; } @@ -989,31 +991,32 @@ TriangleMesh make_cube(double x, double y, double z) // Generate the mesh for a cylinder and return it, using // the generated angle to calculate the top mesh triangles. // Default is 360 sides, angle fa is in radians. -TriangleMesh make_cylinder(double r, double h, double fa) +indexed_triangle_set its_make_cylinder(double r, double h, double fa) { + indexed_triangle_set mesh; size_t n_steps = (size_t)ceil(2. * PI / fa); double angle_step = 2. * PI / n_steps; - Pointf3s vertices; - std::vector facets; + auto &vertices = mesh.vertices; + auto &facets = mesh.indices; vertices.reserve(2 * n_steps + 2); facets.reserve(4 * n_steps); // 2 special vertices, top and bottom center, rest are relative to this - vertices.emplace_back(Vec3d(0.0, 0.0, 0.0)); - vertices.emplace_back(Vec3d(0.0, 0.0, h)); + vertices.emplace_back(Vec3f(0.f, 0.f, 0.f)); + vertices.emplace_back(Vec3f(0.f, 0.f, float(h))); // for each line along the polygon approximating the top/bottom of the // circle, generate four points and four facets (2 for the wall, 2 for the // top and bottom. // Special case: Last line shares 2 vertices with the first line. - Vec2d p = Eigen::Rotation2Dd(0.) * Eigen::Vector2d(0, r); - vertices.emplace_back(Vec3d(p(0), p(1), 0.)); - vertices.emplace_back(Vec3d(p(0), p(1), h)); + Vec2f p = Eigen::Rotation2Df(0.f) * Eigen::Vector2f(0, r); + vertices.emplace_back(Vec3f(p(0), p(1), 0.f)); + vertices.emplace_back(Vec3f(p(0), p(1), float(h))); for (size_t i = 1; i < n_steps; ++i) { - p = Eigen::Rotation2Dd(angle_step * i) * Eigen::Vector2d(0, r); - vertices.emplace_back(Vec3d(p(0), p(1), 0.)); - vertices.emplace_back(Vec3d(p(0), p(1), h)); + p = Eigen::Rotation2Df(angle_step * i) * Eigen::Vector2f(0, float(r)); + vertices.emplace_back(Vec3f(p(0), p(1), 0.f)); + vertices.emplace_back(Vec3f(p(0), p(1), float(h))); int id = (int)vertices.size() - 1; facets.emplace_back( 0, id - 1, id - 3); // top facets.emplace_back(id, 1, id - 2); // bottom @@ -1026,9 +1029,15 @@ TriangleMesh make_cylinder(double r, double h, double fa) facets.emplace_back( 3, 1, id); facets.emplace_back(id, 2, 3); facets.emplace_back(id, id - 1, 2); - - TriangleMesh mesh(std::move(vertices), std::move(facets)); + + return mesh; +} + +TriangleMesh make_cylinder(double r, double h, double fa) +{ + TriangleMesh mesh{its_make_cylinder(r, h, fa)}; mesh.repair(); + return mesh; } @@ -1063,14 +1072,15 @@ TriangleMesh make_cone(double r, double h, double fa) // to determine the granularity. // Default angle is 1 degree. //FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html -TriangleMesh make_sphere(double radius, double fa) +indexed_triangle_set its_make_sphere(double radius, double fa) { int sectorCount = int(ceil(2. * M_PI / fa)); int stackCount = int(ceil(M_PI / fa)); float sectorStep = float(2. * M_PI / sectorCount); float stackStep = float(M_PI / stackCount); - Pointf3s vertices; + indexed_triangle_set mesh; + auto& vertices = mesh.vertices; vertices.reserve((stackCount - 1) * sectorCount + 2); for (int i = 0; i <= stackCount; ++ i) { // from pi/2 to -pi/2 @@ -1078,16 +1088,16 @@ TriangleMesh make_sphere(double radius, double fa) double xy = radius * cos(stackAngle); double z = radius * sin(stackAngle); if (i == 0 || i == stackCount) - vertices.emplace_back(Vec3d(xy, 0., z)); + vertices.emplace_back(Vec3f(float(xy), 0.f, float(z))); else for (int j = 0; j < sectorCount; ++ j) { // from 0 to 2pi double sectorAngle = sectorStep * j; - vertices.emplace_back(Vec3d(xy * cos(sectorAngle), xy * sin(sectorAngle), z)); + vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast()); } } - std::vector facets; + auto& facets = mesh.indices; facets.reserve(2 * (stackCount - 1) * sectorCount); for (int i = 0; i < stackCount; ++ i) { // Beginning of current stack. @@ -1112,8 +1122,15 @@ TriangleMesh make_sphere(double radius, double fa) k2 = k2_next; } } - TriangleMesh mesh(std::move(vertices), std::move(facets)); + + return mesh; +} + +TriangleMesh make_sphere(double radius, double fa) +{ + TriangleMesh mesh(its_make_sphere(radius, fa)); mesh.repair(); + return mesh; } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index bad528202..d02f498e9 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -179,8 +179,14 @@ void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B); void its_merge(indexed_triangle_set &A, const std::vector &triangles); void its_merge(indexed_triangle_set &A, const Pointf3s &triangles); +indexed_triangle_set its_make_cube(double x, double y, double z); TriangleMesh make_cube(double x, double y, double z); + +// Generate a TriangleMesh of a cylinder +indexed_triangle_set its_make_cylinder(double r, double h, double fa=(2*PI/360)); TriangleMesh make_cylinder(double r, double h, double fa=(2*PI/360)); + +indexed_triangle_set its_make_sphere(double rho, double fa=(2*PI/360)); TriangleMesh make_cone(double r, double h, double fa=(2*PI/360)); TriangleMesh make_sphere(double rho, double fa=(2*PI/360));