diff --git a/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp b/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp index d88e9cb684..ab730d2bf1 100644 --- a/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp +++ b/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp @@ -3,6 +3,8 @@ #include +#define OPTION_TO_STORE_ISLAND + namespace Slic3r::sla { /// /// Configuration DTO @@ -77,8 +79,10 @@ struct SampleConfig // (neighbor coordinate - create issue in voronoi) double simplification_tolerance = scale_(0.05 /*mm*/); +#ifdef OPTION_TO_STORE_ISLAND // Only for debug purposes std::string path = ""; // when set to empty string, no debug output is generated +#endif // OPTION_TO_STORE_ISLAND }; } // namespace Slic3r::sla #endif // slic3r_SLA_SuppotstIslands_SampleConfig_hpp_ diff --git a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp index a3e466add1..69f9d3d70e 100644 --- a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp +++ b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp @@ -21,9 +21,6 @@ // comment definition of NDEBUG to enable assert() //#define NDEBUG - -//#define SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH "C:/data/temp/align/island_<>_graph.svg" -//#define SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH "C:/data/temp/align/island_<>_init.svg" //#define SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG_PATH "C:/data/temp/align/island_<>_aligned.svg" @@ -117,21 +114,38 @@ ExPolygon get_simplified(const ExPolygon &island, const SampleConfig &config) { island : get_expolygon_with_biggest_contour(simplified_expolygons); } +#ifdef OPTION_TO_STORE_ISLAND +SVG draw_island(const std::string &path, const ExPolygon &island, const ExPolygon &simplified_island) { + SVG svg(path, BoundingBox{island.contour.points}); + svg.draw_original(island); + svg.draw(island, "lightgray"); + svg.draw(simplified_island, "gray"); + return svg; +} +SVG draw_island_graph(const std::string &path, const ExPolygon &island, + const ExPolygon &simplified_island, const VoronoiGraph& skeleton, + const VoronoiGraph::ExPath& longest_path, const Lines& lines, coord_t width) { + SVG svg = draw_island(path, island, simplified_island); + VoronoiGraphUtils::draw(svg, skeleton, lines, width); + VoronoiGraphUtils::draw(svg, longest_path.nodes, width, "orange"); + return svg; +} +#endif // OPTION_TO_STORE_ISLAND } // namespace SupportIslandPoints SampleIslandUtils::uniform_cover_island( const ExPolygon &island, const SampleConfig &config ) { ExPolygon simplified_island = get_simplified(island, config); - +#ifdef OPTION_TO_STORE_ISLAND + std::string path; if (!config.path.empty()) { static int counter = 0; - std::string path = replace_first(config.path, "<>", std::to_string(++counter)); - SVG svg(path, BoundingBox{island.contour.points}); - svg.draw_original(island); - svg.draw(island, "lightgray"); - svg.draw(simplified_island, "gray"); + path = replace_first(config.path, "<>", std::to_string(++counter)); + draw_island(path, island, simplified_island); + // need to save svg in case of infinite loop so no store SVG into variable } +#endif // OPTION_TO_STORE_ISLAND // When island is smaller than minimal-head diameter, // it will be supported whole by support poin in center @@ -139,7 +153,14 @@ SupportIslandPoints SampleIslandUtils::uniform_cover_island( SupportIslandPoints result; result.push_back(std::make_unique( center, SupportIslandInnerPoint::Type::one_bb_center_point)); +#ifdef OPTION_TO_STORE_ISLAND + if (!path.empty()){ // add center support point into image + SVG svg = draw_island(path, island, simplified_island); + svg.draw(center, "black", config.head_radius); + svg.draw_text(center, "Center of bounding box", "black"); + } return result; +#endif // OPTION_TO_STORE_ISLAND } Slic3r::Geometry::VoronoiDiagram vd; @@ -148,13 +169,39 @@ SupportIslandPoints SampleIslandUtils::uniform_cover_island( Slic3r::Voronoi::annotate_inside_outside(vd, lines); VoronoiGraph skeleton = VoronoiGraphUtils::create_skeleton(vd, lines); VoronoiGraph::ExPath longest_path; - - SupportIslandPoints samples = - SampleIslandUtils::sample_voronoi_graph(skeleton, lines, config, longest_path); + + const VoronoiGraph::Node *start_node = VoronoiGraphUtils::getFirstContourNode(skeleton); + // every island has to have a point on contour + assert(start_node != nullptr); + longest_path = VoronoiGraphUtils::create_longest_path(start_node); + +#ifdef OPTION_TO_STORE_ISLAND // add voronoi diagram with longest path into image + if (!path.empty()) draw_island_graph(path, island, simplified_island, skeleton, longest_path, lines, config.head_radius / 10); +#endif // OPTION_TO_STORE_ISLAND + + SupportIslandPoints samples = sample_expath(longest_path, lines, config); + +#ifdef OPTION_TO_STORE_ISLAND + Points samples_before_align = to_points(samples); + if (!path.empty()) { + SVG svg = draw_island_graph(path, island, simplified_island, skeleton, longest_path, lines, config.head_radius / 10); + draw(svg, samples, config.head_radius); + } +#endif // OPTION_TO_STORE_ISLAND // allign samples SampleIslandUtils::align_samples(samples, island, config); - +#ifdef OPTION_TO_STORE_ISLAND + if (!path.empty()) { + SVG svg = draw_island_graph(path, island, simplified_island, skeleton, longest_path, lines, config.head_radius / 10); + draw(svg, samples, config.head_radius); + Lines align_moves; + align_moves.reserve(samples.size()); + for (size_t i = 0; i < samples.size(); ++i) + align_moves.push_back(Line(samples[i]->point, samples_before_align[i])); + svg.draw(align_moves, "lightgray"); + } +#endif // OPTION_TO_STORE_ISLAND return samples; } @@ -569,17 +616,6 @@ void SampleIslandUtils::align_samples(SupportIslandPoints &samples, } namespace { -Polygons create_voronoi_cells_boost(const Points &points, coord_t max_distance) { - using VD = Slic3r::Geometry::VoronoiDiagram; - VD vd; - vd.construct_voronoi(points.begin(), points.end()); - assert(points.size() == vd.cells().size()); - Polygons cells(points.size()); - for (const VD::cell_type &cell : vd.cells()) - cells[cell.source_index()] = VoronoiGraphUtils::to_polygon(cell, points, max_distance); - return cells; -} - bool is_points_in_distance(const Slic3r::Point & p, const Slic3r::Points &points, double max_distance) @@ -598,16 +634,12 @@ coord_t SampleIslandUtils::align_once( const ExPolygon &island, const SampleConfig &config) { + // IMPROVE: Do not calculate voronoi diagram out of island(only triangulate island) + // https://stackoverflow.com/questions/23823345/how-to-construct-a-voronoi-diagram-inside-a-polygon // IMPROVE1: add accessor to point coordinate do not copy points // IMPROVE2: add filter for create cell polygon only for moveable samples - Slic3r::Points points = SampleIslandUtils::to_points(samples); - - Polygons cell_polygons = /* - create_voronoi_cells_boost - /*/ - create_voronoi_cells_cgal - //*/ - (points, config.max_distance); + Slic3r::Points points = SampleIslandUtils::to_points(samples); + Polygons cell_polygons = create_voronoi_cells_cgal(points, config.max_distance); #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH std::string color_of_island = "#FF8080"; // LightRed. Should not be visible - cell color should overlap @@ -1032,43 +1064,6 @@ SupportIslandPoints SampleIslandUtils::sample_center_circle( return result; } -SupportIslandPoints SampleIslandUtils::sample_voronoi_graph( - const VoronoiGraph & graph, - const Lines & lines, - const SampleConfig & config, - VoronoiGraph::ExPath &longest_path) -{ - const VoronoiGraph::Node *start_node = - VoronoiGraphUtils::getFirstContourNode(graph); - // every island has to have a point on contour - assert(start_node != nullptr); - longest_path = VoronoiGraphUtils::create_longest_path(start_node); - -#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH - { - static int counter = 0; - SVG svg(replace_first(SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH, - "<>", std::to_string(counter++)).c_str(), LineUtils::create_bounding_box(lines)); - VoronoiGraphUtils::draw(svg, graph, lines, config.head_radius / 10, true); - VoronoiGraphUtils::draw(svg, longest_path, config.head_radius / 10); - } -#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH - - SupportIslandPoints points = sample_expath(longest_path, lines, config); - -#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH - { - static int counter = 0; - SVG svg(replace_first(SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH, - "<>", std::to_string(counter++)).c_str(), - LineUtils::create_bounding_box(lines)); - svg.draw(lines, "gray", config.head_radius/ 10); - draw(svg, points, config.head_radius, "black", true); - } -#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH - return points; -} - SupportIslandPoints SampleIslandUtils::sample_expath( const VoronoiGraph::ExPath &path, const Lines & lines, @@ -1796,7 +1791,6 @@ SupportIslandPoints SampleIslandUtils::sample_outline( const double &line_length_double = restriction->lengths[index]; coord_t line_length = static_cast(std::round(line_length_double)); if (last_support + line_length > sample_distance) { - Point direction = LineUtils::direction(line); do { double ratio = (sample_distance - last_support) / line_length_double; result.emplace_back( @@ -2036,12 +2030,6 @@ bool SampleIslandUtils::is_visualization_disabled() #ifndef NDEBUG return false; #endif -#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG_PATH - return false; -#endif -#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH - return false; -#endif #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG return false; #endif diff --git a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp index 8efb79c94a..308b56a915 100644 --- a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp +++ b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp @@ -183,21 +183,6 @@ public: const CenterLineConfiguration & cfg, SupportIslandPoints & result); - /// - /// Sample voronoi skeleton - /// - /// Inside skeleton of island - /// Source lines for VG --> outline of island. - /// Params for sampling - /// OUTPUT: longest path in graph - /// Vector of sampled points or Empty when distance from edge is - /// bigger than max_distance - static SupportIslandPoints sample_voronoi_graph( - const VoronoiGraph & graph, - const Lines & lines, - const SampleConfig & config, - VoronoiGraph::ExPath &longest_path); - /// /// Decide how to sample path /// diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c2e9e469fc..cb258b18e7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -813,6 +813,8 @@ void GLGizmoSlaSupports::draw_island_config() { if (!ImGui::TreeNode("Support islands:")) return; // no need to draw configuration for islands sla::SampleConfig &sample_config = sla::SampleConfigFactory::get_sample_config(); + +#ifdef OPTION_TO_STORE_ISLAND bool store_islands = !sample_config.path.empty(); if (ImGui::Checkbox("StoreIslands", &store_islands)) { if (store_islands = true) @@ -824,6 +826,7 @@ void GLGizmoSlaSupports::draw_island_config() { std::string path; ImGui::InputText("path", &sample_config.path); } +#endif // OPTION_TO_STORE_ISLAND bool exist_change = false; if (float simplification_tolerance = unscale(sample_config.simplification_tolerance); // [in mm] diff --git a/tests/sla_print/sla_supptgen_tests.cpp b/tests/sla_print/sla_supptgen_tests.cpp index f221d337e4..650400f435 100644 --- a/tests/sla_print/sla_supptgen_tests.cpp +++ b/tests/sla_print/sla_supptgen_tests.cpp @@ -356,7 +356,7 @@ ExPolygons createTestIslands(double size) bool useFrogLeg = false; // need post reorganization of longest path ExPolygons result = { - load_svg("C:/Users/Filip Sykala/Downloads/lm_issue.svg"), + //load_svg("C:/Users/Filip Sykala/Downloads/lm_issue.svg"), // one support point ExPolygon(PolygonUtils::create_equilateral_triangle(size)), ExPolygon(PolygonUtils::create_square(size)), @@ -525,98 +525,8 @@ SampleConfig create_sample_config(double size) { return cfg; } -#include -#include -TEST_CASE("Sampling speed test on FrogLegs", "[hide], [VoronoiSkeleton]") -{ - TriangleMesh mesh = load_model("frog_legs.obj"); - std::vector grid({0.1f}); - std::vector slices = slice_mesh_ex(mesh.its, {0.1f}); - ExPolygon frog_leg = slices.front()[1]; - SampleConfig cfg = create_sample_config(3e7); - - using VD = Slic3r::Geometry::VoronoiDiagram; - VD vd; - Lines lines = to_lines(frog_leg); - vd.construct_voronoi(lines.begin(), lines.end()); - Slic3r::Voronoi::annotate_inside_outside(vd, lines); - - for (int i = 0; i < 100; ++i) { - VoronoiGraph::ExPath longest_path; - VoronoiGraph skeleton = VoronoiGraphUtils::create_skeleton(vd, lines); - auto samples = SampleIslandUtils::sample_voronoi_graph(skeleton, lines, cfg, longest_path); - } -} - -TEST_CASE("Speed align", "[hide], [VoronoiSkeleton]") -{ - SampleConfig cfg = create_sample_config(3e7); - cfg.max_align_distance = 1000; - cfg.count_iteration = 1000; - cfg.max_align_distance = 3e7; - - double size = 3e7; - auto island = create_square_with_4holes(5 * size, 5 * size / 2 - size / 3); - using VD = Slic3r::Geometry::VoronoiDiagram; - VD vd; - Lines lines = to_lines(island); - vd.construct_voronoi(lines.begin(), lines.end()); - Slic3r::Voronoi::annotate_inside_outside(vd, lines); - VoronoiGraph::ExPath longest_path; - VoronoiGraph skeleton = VoronoiGraphUtils::create_skeleton(vd, lines); - - for (int i = 0; i < 100; ++i) { - auto samples = SampleIslandUtils::sample_voronoi_graph(skeleton, lines, cfg, longest_path); - SampleIslandUtils::align_samples(samples, island, cfg); - } -} - -#include -/// -/// Check speed of sampling, -/// for be sure that code is not optimized out store result to svg or print count. -/// -TEST_CASE("speed sampling", "[hide], [SupGen]") { - double size = 3e7; - float samples_per_mm2 = 0.01f; - ExPolygons islands = createTestIslands(size); - std::random_device rd; - std::mt19937 m_rng; - m_rng.seed(rd()); - - size_t count = 1; - - std::vector> result2; - result2.reserve(islands.size()*count); - for (size_t i = 0; i < count; ++i) - for (const auto &island : islands) - result2.emplace_back(SampleIslandUtils::sample_expolygon(island, samples_per_mm2)); //*/ - - /*size_t all = 0; - for (auto& result : result2) { - //std::cout << "case " << &result - &result1[0] << " points " << result.size() << std::endl; - all += result.size(); - } - std::cout << "All points " << all << std::endl;*/ - - #ifdef STORE_SAMPLE_INTO_SVG_FILES - for (size_t i = 0; i < result2.size(); ++i) { - size_t island_index = i % islands.size(); - ExPolygon &island = islands[island_index]; - - Lines lines = to_lines(island.contour); - std::string name = "sample_" + std::to_string(i) + ".svg"; - SVG svg(name, LineUtils::create_bounding_box(lines)); - svg.draw(island, "lightgray"); - svg.draw_text({0., 5e6}, ("uniform samples " + std::to_string(result2[i].size())).c_str(), "green"); - for (Vec2f &p : result2[i]) - svg.draw((p * 1e6).cast(), "green", 1e6); - } -#endif // STORE_SAMPLE_INTO_SVG_FILES -} namespace { - void store_sample(const SupportIslandPoints &samples, const ExPolygon &island) { static int counter = 0; BoundingBox bb(island.contour.points); @@ -639,8 +549,8 @@ void store_sample(const SupportIslandPoints &samples, const ExPolygon &island) { for (int i=0; i<10;i+=2) svg.draw(Line(start + Point(i*mm, 0.), start + Point((i+1)*mm, 0.)), "black", 1e6); } - } // namespace +#endif // STORE_SAMPLE_INTO_SVG_FILES /// /// Check for correct sampling of island @@ -649,6 +559,7 @@ TEST_CASE("Uniform sample test islands", "[SupGen], [VoronoiSkeleton]") { float head_diameter = .4f; SampleConfig cfg = SampleConfigFactory::create(head_diameter); + //cfg.path = "C:/data/temp/island<>.svg"; ExPolygons islands = createTestIslands(7 * scale_(head_diameter)); for (ExPolygon &island : islands) { // information for debug which island cause problem