mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-09-18 20:43:15 +08:00
Fix for creating wide tiny change.
+ unify runtime by selecting position with smallest source index
This commit is contained in:
parent
ac2f6304a0
commit
cb20051e03
@ -39,6 +39,8 @@ std::string SupportIslandPoint::to_string(const Type &type)
|
|||||||
{Type::thin_part_loop, "thin_part_loop"},
|
{Type::thin_part_loop, "thin_part_loop"},
|
||||||
{Type::thick_part_outline, "thick_part_outline"},
|
{Type::thick_part_outline, "thick_part_outline"},
|
||||||
{Type::thick_part_inner, "thick_part_inner"},
|
{Type::thick_part_inner, "thick_part_inner"},
|
||||||
|
{Type::bad_shape_for_vd, "bad_shape_for_vd"},
|
||||||
|
{Type::permanent, "permanent"},
|
||||||
{Type::undefined, "undefined"}};
|
{Type::undefined, "undefined"}};
|
||||||
auto it = type_to_string.find(type);
|
auto it = type_to_string.find(type);
|
||||||
if (it == type_to_string.end())
|
if (it == type_to_string.end())
|
||||||
|
@ -431,10 +431,10 @@ coord_t align_once(
|
|||||||
SupportIslandPointPtr &support = supports[i];
|
SupportIslandPointPtr &support = supports[i];
|
||||||
|
|
||||||
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
if (!sample->can_move()) { // draww freezed support points
|
if (!support->can_move()) { // draww freezed support points
|
||||||
svg.draw(sample->point, color_static_point, config.head_radius);
|
svg.draw(support->point, color_static_point, config.head_radius);
|
||||||
svg.draw_text(sample->point + Point(config.head_radius, 0),
|
svg.draw_text(support->point + Point(config.head_radius, 0),
|
||||||
SupportIslandPoint::to_string(sample->type).c_str(), color_static_point.c_str());
|
SupportIslandPoint::to_string(support->type).c_str(), color_static_point.c_str());
|
||||||
}
|
}
|
||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
if (!support->can_move())
|
if (!support->can_move())
|
||||||
@ -488,8 +488,8 @@ coord_t align_once(
|
|||||||
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
svg.draw(cell_polygon, color_point_cell);
|
svg.draw(cell_polygon, color_point_cell);
|
||||||
svg.draw(*island_cell, color_island_cell_intersection);
|
svg.draw(*island_cell, color_island_cell_intersection);
|
||||||
svg.draw(Line(sample->point, island_cell_center), color_wanted_point, config.head_radius / 5);
|
svg.draw(Line(support->point, island_cell_center), color_wanted_point, config.head_radius / 5);
|
||||||
svg.draw(sample->point, color_old_point, config.head_radius);
|
svg.draw(support->point, color_old_point, config.head_radius);
|
||||||
svg.draw(island_cell_center, color_wanted_point, config.head_radius); // wanted position
|
svg.draw(island_cell_center, color_wanted_point, config.head_radius); // wanted position
|
||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
|
|
||||||
@ -499,9 +499,10 @@ coord_t align_once(
|
|||||||
max_move = act_move;
|
max_move = act_move;
|
||||||
|
|
||||||
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
svg.draw(sample->point, color_new_point, config.head_radius);
|
svg.draw(support->point, color_new_point, config.head_radius);
|
||||||
svg.draw_text(sample->point + Point(config.head_radius, 0),
|
svg.draw_text(support->point + Point(config.head_radius, 0),
|
||||||
SupportIslandPoint::to_string(sample->type).c_str(), color_new_point.c_str());
|
SupportIslandPoint::to_string(support->type).c_str(), color_new_point.c_str()
|
||||||
|
);
|
||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG_PATH
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,7 +641,7 @@ using ThinParts = std::vector<ThinPart>;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
struct ThickPart
|
struct ThickPart
|
||||||
{
|
{
|
||||||
// neighbor from thick part (twin of first end)
|
// neighbor from thick part (twin of end with smallest source line index)
|
||||||
// edge from thin to thick, start.node is inside of thick part
|
// edge from thin to thick, start.node is inside of thick part
|
||||||
const Neighbor* start;
|
const Neighbor* start;
|
||||||
|
|
||||||
@ -1099,45 +1100,39 @@ void draw(SVG &svg, const Field &field, const ExPolygon& border, bool draw_borde
|
|||||||
}
|
}
|
||||||
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG_PATH || SLA_SAMPLE_ISLAND_UTILS_STORE_PENINSULA_FIELD_TO_SVG_PATH
|
#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG_PATH || SLA_SAMPLE_ISLAND_UTILS_STORE_PENINSULA_FIELD_TO_SVG_PATH
|
||||||
|
|
||||||
|
std::map<size_t, WideTinyChanges> create_wide_tiny_changes(const Positions& part_ends, const Lines &lines) {
|
||||||
|
std::map<size_t, WideTinyChanges> wide_tiny_changes;
|
||||||
|
// part_ends are already oriented
|
||||||
|
for (const Position &position : part_ends) {
|
||||||
|
Point p1, p2;
|
||||||
|
std::tie(p2, p1) = VoronoiGraphUtils::point_on_lines(position, lines);
|
||||||
|
const VD::edge_type *edge = position.neighbor->edge;
|
||||||
|
size_t i1 = edge->twin()->cell()->source_index();
|
||||||
|
size_t i2 = edge->cell()->source_index();
|
||||||
|
|
||||||
|
// add sorted change from wide to tiny
|
||||||
|
// stored uder line index or line shorten in point b
|
||||||
|
WideTinyChange change(p1, p2, i2);
|
||||||
|
auto item = wide_tiny_changes.find(i1);
|
||||||
|
if (item == wide_tiny_changes.end()) {
|
||||||
|
wide_tiny_changes[i1] = {change};
|
||||||
|
} else {
|
||||||
|
WideTinyChange::SortFromAToB pred(lines[i1]);
|
||||||
|
VectorUtils::insert_sorted(item->second, change, pred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wide_tiny_changes;
|
||||||
|
}
|
||||||
|
|
||||||
// IMPROVE do not use pointers on node but pointers on Neighbor
|
// IMPROVE do not use pointers on node but pointers on Neighbor
|
||||||
Field create_thick_field(const ThickPart& part, const Lines &lines, const SampleConfig &config)
|
Field create_thick_field(const ThickPart& part, const Lines &lines, const SampleConfig &config)
|
||||||
{
|
{
|
||||||
// store shortening of outline segments
|
// store shortening of outline segments
|
||||||
// line index, vector<next line index + 2x shortening points>
|
// line index, vector<next line index + 2x shortening points>
|
||||||
std::map<size_t, WideTinyChanges> wide_tiny_changes;
|
std::map<size_t, WideTinyChanges> wide_tiny_changes = create_wide_tiny_changes(part.ends, lines);
|
||||||
for (const Position &position : part.ends) {
|
|
||||||
Point p1, p2;
|
|
||||||
std::tie(p1, p2) = VoronoiGraphUtils::point_on_lines(position, lines);
|
|
||||||
const VD::edge_type *edge = position.neighbor->edge;
|
|
||||||
size_t i1 = edge->cell()->source_index();
|
|
||||||
size_t i2 = edge->twin()->cell()->source_index();
|
|
||||||
|
|
||||||
// function to add sorted change from wide to tiny
|
|
||||||
// stored uder line index or line shorten in point b
|
|
||||||
auto add = [&wide_tiny_changes, &lines](const Point &p1, const Point &p2, size_t i1, size_t i2) {
|
|
||||||
WideTinyChange change(p1, p2, i2);
|
|
||||||
auto item = wide_tiny_changes.find(i1);
|
|
||||||
if (item == wide_tiny_changes.end()) {
|
|
||||||
wide_tiny_changes[i1] = {change};
|
|
||||||
} else {
|
|
||||||
WideTinyChange::SortFromAToB pred(lines[i1]);
|
|
||||||
VectorUtils::insert_sorted(item->second, change, pred);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Line &l1 = lines[i1];
|
|
||||||
if (VoronoiGraphUtils::is_opposit_direction(edge, l1)) {
|
|
||||||
// line1 is shorten on side line1.a --> line2 is shorten on side line2.b
|
|
||||||
add(p2, p1, i2, i1);
|
|
||||||
} else {
|
|
||||||
// line1 is shorten on side line1.b
|
|
||||||
add(p1, p2, i1, i2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// connection of line on island
|
// connection of line on island
|
||||||
std::map<size_t, size_t> b_connection =
|
std::map<size_t, size_t> b_connection = LineUtils::create_line_connection_over_b(lines);
|
||||||
LineUtils::create_line_connection_over_b(lines);
|
|
||||||
|
|
||||||
std::vector<size_t> source_indices;
|
std::vector<size_t> source_indices;
|
||||||
auto inser_point_b = [&lines, &b_connection, &source_indices]
|
auto inser_point_b = [&lines, &b_connection, &source_indices]
|
||||||
@ -2240,6 +2235,27 @@ ThinPart create_only_thin_part(const VoronoiGraph::ExPath &path) {
|
|||||||
return ThinPart{*path_center_opt, /*ends*/ {}};
|
return ThinPart{*path_center_opt, /*ends*/ {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VoronoiGraph::Node::Neighbor *get_smallest_source_index(const Positions& positions){
|
||||||
|
// do not call with empty positions
|
||||||
|
assert(!positions.empty());
|
||||||
|
if (positions.size() == 1)
|
||||||
|
return positions.front().neighbor;
|
||||||
|
|
||||||
|
const VoronoiGraph::Node::Neighbor *smallest = nullptr;
|
||||||
|
size_t smallest_index = std::numeric_limits<size_t>::max();
|
||||||
|
for (const Position &position : positions) {
|
||||||
|
const VD::edge_type *e = position.neighbor->edge;
|
||||||
|
size_t min_index = std::min(
|
||||||
|
e->cell()->source_index(),
|
||||||
|
e->twin()->cell()->source_index());
|
||||||
|
if (smallest_index > min_index) {
|
||||||
|
smallest_index = min_index;
|
||||||
|
smallest = position.neighbor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return smallest;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<ThinParts, ThickParts> convert_island_parts_to_thin_thick(
|
std::pair<ThinParts, ThickParts> convert_island_parts_to_thin_thick(
|
||||||
const IslandParts& island_parts, const VoronoiGraph::ExPath &path)
|
const IslandParts& island_parts, const VoronoiGraph::ExPath &path)
|
||||||
{
|
{
|
||||||
@ -2273,8 +2289,9 @@ std::pair<ThinParts, ThickParts> convert_island_parts_to_thin_thick(
|
|||||||
thin_parts.push_back(ThinPart{center, std::move(ends)});
|
thin_parts.push_back(ThinPart{center, std::move(ends)});
|
||||||
} else {
|
} else {
|
||||||
assert(i.type == IslandPartType::thick);
|
assert(i.type == IslandPartType::thick);
|
||||||
//const Neighbor* start = polygon_index.changes.front().position.neighbor;
|
const Neighbor *start = VoronoiGraphUtils::get_twin(*get_smallest_source_index(ends));
|
||||||
const Neighbor *start = VoronoiGraphUtils::get_twin(*ends.front().neighbor);
|
// NOTE: VD could contain different order of edges each run.
|
||||||
|
// To unify behavior as a start index is selected edge with smallest index of source line
|
||||||
thick_parts.push_back(ThickPart {start, std::move(ends)});
|
thick_parts.push_back(ThickPart {start, std::move(ends)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ using namespace Slic3r;
|
|||||||
using namespace Slic3r::sla;
|
using namespace Slic3r::sla;
|
||||||
|
|
||||||
//#define STORE_SAMPLE_INTO_SVG_FILES "C:/data/temp/test_islands/sample_"
|
//#define STORE_SAMPLE_INTO_SVG_FILES "C:/data/temp/test_islands/sample_"
|
||||||
|
//#define STORE_ISLAND_ISSUES "C:/data/temp/issues/"
|
||||||
|
|
||||||
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
TEST_CASE("Overhanging point should be supported", "[SupGen]") {
|
||||||
|
|
||||||
@ -69,9 +70,6 @@ TEST_CASE("Overhanging horizontal surface should be supported", "[SupGen]") {
|
|||||||
mesh.translate(0., 0., 5.); // lift up
|
mesh.translate(0., 0., 5.); // lift up
|
||||||
// mesh.WriteOBJFile("Cuboid.obj");
|
// mesh.WriteOBJFile("Cuboid.obj");
|
||||||
sla::SupportPoints pts = calc_support_pts(mesh);
|
sla::SupportPoints pts = calc_support_pts(mesh);
|
||||||
|
|
||||||
double mm2 = width * depth;
|
|
||||||
|
|
||||||
REQUIRE(!pts.empty());
|
REQUIRE(!pts.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +323,7 @@ ExPolygon load_svg(const std::string& svg_filepath) {
|
|||||||
auto to_polygon = [](NSVGpath *path) {
|
auto to_polygon = [](NSVGpath *path) {
|
||||||
Polygon r;
|
Polygon r;
|
||||||
r.points.reserve(path->npts);
|
r.points.reserve(path->npts);
|
||||||
for (size_t i = 0; i < path->npts; i++)
|
for (int i = 0; i < path->npts; i++)
|
||||||
r.points.push_back(Point(path->pts[2 * i], path->pts[2 * i + 1]));
|
r.points.push_back(Point(path->pts[2 * i], path->pts[2 * i + 1]));
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
@ -455,10 +453,9 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
|||||||
auto points = uniform_support_island(island, {}, config);
|
auto points = uniform_support_island(island, {}, config);
|
||||||
|
|
||||||
Points chck_points = rasterize(island, config.head_radius); // TODO: Use resolution of printer
|
Points chck_points = rasterize(island, config.head_radius); // TODO: Use resolution of printer
|
||||||
bool is_ok = true;
|
bool is_island_supported = true; // Check rasterized island points that exist support point in max_distance
|
||||||
double max_distance = config.thick_inner_max_distance;
|
double max_distance = config.thick_inner_max_distance;
|
||||||
std::vector<double> point_distances(chck_points.size(),
|
std::vector<double> point_distances(chck_points.size(), {max_distance + 1});
|
||||||
{max_distance + 1});
|
|
||||||
for (size_t index = 0; index < chck_points.size(); ++index) {
|
for (size_t index = 0; index < chck_points.size(); ++index) {
|
||||||
const Point &chck_point = chck_points[index];
|
const Point &chck_point = chck_points[index];
|
||||||
double &min_distance = point_distances[index];
|
double &min_distance = point_distances[index];
|
||||||
@ -473,20 +470,26 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
|||||||
if (min_distance > distance) {
|
if (min_distance > distance) {
|
||||||
min_distance = distance;
|
min_distance = distance;
|
||||||
exist_close_support_point = true;
|
exist_close_support_point = true;
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!exist_close_support_point) is_ok = false;
|
if (!exist_close_support_point) is_island_supported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_ok) { // visualize
|
bool is_all_points_inside_island = true;
|
||||||
static int counter = 0;
|
for (const auto &point : points)
|
||||||
|
if (!island.contains(point->point))
|
||||||
|
is_all_points_inside_island = false;
|
||||||
|
|
||||||
|
#ifdef STORE_ISLAND_ISSUES
|
||||||
|
if (!is_island_supported || !is_all_points_inside_island) { // visualize
|
||||||
|
static int counter = 0;
|
||||||
BoundingBox bb;
|
BoundingBox bb;
|
||||||
for (const Point &pt : island.contour.points) bb.merge(pt);
|
for (const Point &pt : island.contour.points) bb.merge(pt);
|
||||||
SVG svg("Error" + std::to_string(++counter) + ".svg", bb);
|
SVG svg(STORE_ISLAND_ISSUES + std::string("Error") + std::to_string(++counter) + ".svg", bb);
|
||||||
svg.draw(island, "blue", 0.5f);
|
svg.draw(island, "blue", 0.5f);
|
||||||
for (auto& p : points)
|
for (auto& p : points)
|
||||||
svg.draw(p->point, "lightgreen", config.head_radius);
|
svg.draw(p->point, island.contains(p->point) ? "lightgreen" : "red", config.head_radius);
|
||||||
for (size_t index = 0; index < chck_points.size(); ++index) {
|
for (size_t index = 0; index < chck_points.size(); ++index) {
|
||||||
const Point &chck_point = chck_points[index];
|
const Point &chck_point = chck_points[index];
|
||||||
double distance = point_distances[index];
|
double distance = point_distances[index];
|
||||||
@ -495,12 +498,12 @@ SupportIslandPoints test_island_sampling(const ExPolygon & island,
|
|||||||
svg.draw(chck_point, color, config.head_radius / 4);
|
svg.draw(chck_point, color, config.head_radius / 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CHECK(!points.empty());
|
#endif // STORE_ISLAND_ISSUES
|
||||||
// TODO: solve issue
|
|
||||||
//CHECK(is_ok);
|
CHECK(!points.empty());
|
||||||
|
CHECK(is_all_points_inside_island);
|
||||||
|
// CHECK(is_island_supported); // TODO: skip special cases with one point and 2 points
|
||||||
|
|
||||||
// all points must be inside of island
|
|
||||||
for (const auto &point : points) { CHECK(island.contains(point->point)); }
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,6 +560,7 @@ void store_sample(const SupportIslandPoints &samples, const ExPolygon &island) {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
TEST_CASE("Uniform sample test islands", "[SupGen], [VoronoiSkeleton]")
|
TEST_CASE("Uniform sample test islands", "[SupGen], [VoronoiSkeleton]")
|
||||||
{
|
{
|
||||||
|
//set_logging_level(5);
|
||||||
float head_diameter = .4f;
|
float head_diameter = .4f;
|
||||||
SampleConfig cfg = SampleConfigFactory::create(head_diameter);
|
SampleConfig cfg = SampleConfigFactory::create(head_diameter);
|
||||||
//cfg.path = "C:/data/temp/islands/<<order>>.svg";
|
//cfg.path = "C:/data/temp/islands/<<order>>.svg";
|
||||||
@ -589,6 +593,9 @@ TEST_CASE("Disable visualization", "[hide]")
|
|||||||
#ifdef STORE_SAMPLE_INTO_SVG_FILES
|
#ifdef STORE_SAMPLE_INTO_SVG_FILES
|
||||||
CHECK(false);
|
CHECK(false);
|
||||||
#endif // STORE_SAMPLE_INTO_SVG_FILES
|
#endif // STORE_SAMPLE_INTO_SVG_FILES
|
||||||
|
#ifdef STORE_ISLAND_ISSUES
|
||||||
|
CHECK(false);
|
||||||
|
#endif // STORE_ISLAND_ISSUES
|
||||||
CHECK(is_uniform_support_island_visualization_disabled());
|
CHECK(is_uniform_support_island_visualization_disabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user