SPE-2709: Fix precision of calculation line cross for thick field creation purpose:

Fixes freezing of SLA support point generator in certain cases
This commit is contained in:
Filip Sykala - NTB T15p 2025-03-04 18:01:55 +01:00 committed by Lukas Matena
parent f6a60c3e84
commit faa778d349
4 changed files with 1243 additions and 7 deletions

View File

@ -1164,10 +1164,9 @@ Field create_thick_field(const ThickPart& part, const Lines &lines, const Sample
assert(!changes.empty());
size_t change_index = 0;
if (!points.empty()) { // Not first point, could lead to termination
const Point &last_point = points.back();
LineUtils::SortFromAToB pred(lines[index]);
bool no_change = false;
while (pred.compare(changes[change_index].new_b, last_point)) {
while (pred.compare(changes[change_index].new_b, points.back())) {
++change_index;
if (change_index >= changes.size()) {
no_change = true;
@ -1244,13 +1243,39 @@ Field create_thick_field(const ThickPart& part, const Lines &lines, const Sample
size_t outline_index = input_index;
// Done indexes is used to detect holes in field
std::set<size_t> done_indices; // IMPROVE: use vector(size of lines count) with bools
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG_PATH
static int counter = 0;
std::string field_to_svg_path = replace_first(
SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG_PATH, "<<COUNTER>>", std::to_string(counter++));
{
SVG svg(field_to_svg_path.c_str(), LineUtils::create_bounding_box(lines));
LineUtils::draw(svg, lines, "black", 0., /*indices*/ true);
for(const auto& change_it: wide_tiny_changes)
for (const auto& change: change_it.second){
Line bisector(change.new_b, change.next_new_a);
LineUtils::draw(svg, bisector, "red");
std::string text = "from " + std::to_string(change_it.first)
+ " to " + std::to_string(change.next_line_index);
svg.draw_text(bisector.a/2 + bisector.b/2, text.c_str(), "orange");
}
} // flush svg file
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG_PATH
do {
if (!insert_changes(outline_index, points, done_indices, input_index))
break;
inser_point_b(outline_index, points, done_indices);
if (points.size() > (lines.size() + 2*part.ends.size())){
// protection against endless loop
assert(false);
return {};
}
} while (outline_index != input_index);
assert(points.size() >= 3);
if (points.size() < 3)
return {}; // invalid field
ExPolygon border{Polygon{points}};
// finding holes(another closed polygon)
if (done_indices.size() < field_line_indices.size()) {
@ -1279,9 +1304,7 @@ Field create_thick_field(const ThickPart& part, const Lines &lines, const Sample
bool draw_source_line_indexes = true;
bool draw_border_line_indexes = false;
bool draw_field_source_indexes = true;
static int counter = 0;
SVG svg(replace_first(SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG_PATH,
"<<COUNTER>>", std::to_string(counter++)).c_str(),LineUtils::create_bounding_box(lines));
SVG svg(field_to_svg_path.c_str(),LineUtils::create_bounding_box(lines));
LineUtils::draw(svg, lines, source_line_color, 0., draw_source_line_indexes);
draw(svg, field, border, draw_border_line_indexes, draw_field_source_indexes);
}

View File

@ -1000,7 +1000,16 @@ std::pair<Slic3r::Point, Slic3r::Point> VoronoiGraphUtils::point_on_lines(
Line intersecting_line(edge_point, edge_point + PointUtils::perp(dir));
std::optional<Vec2d> intersection = LineUtils::intersection(line, intersecting_line);
assert(intersection.has_value());
return intersection->cast<coord_t>();
Point result = intersection->cast<coord_t>();
// result MUST lay on the line, accuracy of float intersection could move point out of line
coord_t tolerance = 5; // for sure it is 5 but found case which need tolerance(1) - SPE-2709
if (abs(result.x() - line.a.x()) < tolerance &&
abs(result.y() - line.a.y()) < tolerance)
return line.a; // almost point a
if (abs(result.x() - line.b.x()) < tolerance &&
abs(result.y() - line.b.y()) < tolerance)
return line.b; // almost point b
return result;
};
return {point_on_line(edge), point_on_line(edge->twin())};

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 189 KiB

View File

@ -587,6 +587,34 @@ TEST_CASE("Uniform sample test islands", "[SupGen], [VoronoiSkeleton]")
}
}
TEST_CASE("Sample island with config", "[SupportIsland]") {
// set_logging_level(5);
SampleConfig cfg{
/*thin_max_distance*/ 5832568,
/*thick_inner_max_distance*/ 7290710,
/*thick_outline_max_distance*/ 5468032,
/*head_radius*/ 250000,
/*minimal_distance_from_outline*/ 250000,
/*maximal_distance_from_outline*/ 1944189,
/*max_length_for_one_support_point*/ 1869413,
/*max_length_for_two_support_points*/ 7290710,
/*max_length_ratio_for_two_support_points*/ 0.250000000f,
/*thin_max_width*/ 4673532,
/*thick_min_width*/ 4019237,
/*min_part_length*/ 5832568,
/*minimal_move*/ 100000,
/*count_iteration*/ 30,
/*max_align_distance*/ 3645355,
/*simplification_tolerance*/ 50000.000000000007
//*path*/, "C:/data/temp/islands/<<order>>.svg" // need define OPTION_TO_STORE_ISLAND in SampleConfig.hpp
};
std::string dir = std::string(TEST_DATA_DIR PATH_SEPARATOR) + "sla_islands/";
ExPolygon island = load_svg(dir + "SPE-2709.svg"); // Bad field creation
SupportIslandPoints points = test_island_sampling(island, cfg);
// in time of write poins.size() == 39
CHECK(points.size() > 22); // not only thin parts
}
TEST_CASE("Disable visualization", "[hide]")
{
CHECK(true);