mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-31 05:22:01 +08:00
Advanced visualization to store island
This commit is contained in:
parent
35948c0361
commit
73f8583e18
@ -3,6 +3,8 @@
|
||||
|
||||
#include <libslic3r/libslic3r.h>
|
||||
|
||||
#define OPTION_TO_STORE_ISLAND
|
||||
|
||||
namespace Slic3r::sla {
|
||||
/// <summary>
|
||||
/// 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_
|
||||
|
@ -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_<<COUNTER>>_graph.svg"
|
||||
//#define SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG_PATH "C:/data/temp/align/island_<<COUNTER>>_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_<<COUNTER>>_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, "<<order>>", 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, "<<order>>", 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<SupportIslandNoMovePoint>(
|
||||
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,
|
||||
"<<COUNTER>>", 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,
|
||||
"<<COUNTER>>", 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<coord_t>(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
|
||||
|
@ -183,21 +183,6 @@ public:
|
||||
const CenterLineConfiguration & cfg,
|
||||
SupportIslandPoints & result);
|
||||
|
||||
/// <summary>
|
||||
/// Sample voronoi skeleton
|
||||
/// </summary>
|
||||
/// <param name="graph">Inside skeleton of island</param>
|
||||
/// <param name="lines">Source lines for VG --> outline of island.</param>
|
||||
/// <param name="config">Params for sampling</param>
|
||||
/// <param name="longest_path">OUTPUT: longest path in graph</param>
|
||||
/// <returns>Vector of sampled points or Empty when distance from edge is
|
||||
/// bigger than max_distance</returns>
|
||||
static SupportIslandPoints sample_voronoi_graph(
|
||||
const VoronoiGraph & graph,
|
||||
const Lines & lines,
|
||||
const SampleConfig & config,
|
||||
VoronoiGraph::ExPath &longest_path);
|
||||
|
||||
/// <summary>
|
||||
/// Decide how to sample path
|
||||
/// </summary>
|
||||
|
@ -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<float>(sample_config.simplification_tolerance); // [in mm]
|
||||
|
@ -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 <libslic3r/Geometry.hpp>
|
||||
#include <libslic3r/Geometry/VoronoiOffset.hpp>
|
||||
TEST_CASE("Sampling speed test on FrogLegs", "[hide], [VoronoiSkeleton]")
|
||||
{
|
||||
TriangleMesh mesh = load_model("frog_legs.obj");
|
||||
std::vector<float> grid({0.1f});
|
||||
std::vector<ExPolygons> 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 <libslic3r/SLA/SupportIslands/LineUtils.hpp>
|
||||
/// <summary>
|
||||
/// Check speed of sampling,
|
||||
/// for be sure that code is not optimized out store result to svg or print count.
|
||||
/// </summary>
|
||||
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<std::vector<Vec2f>> 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<coord_t>(), "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
|
||||
|
||||
/// <summary>
|
||||
/// 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<<order>>.svg";
|
||||
ExPolygons islands = createTestIslands(7 * scale_(head_diameter));
|
||||
for (ExPolygon &island : islands) {
|
||||
// information for debug which island cause problem
|
||||
|
Loading…
x
Reference in New Issue
Block a user