Merge branch 'lh_mm_segmentation'
This commit is contained in:
commit
7ce13b4a26
@ -44,6 +44,8 @@ struct segment_traits<Slic3r::ColoredLine> {
|
||||
//#define MMU_SEGMENTATION_DEBUG_GRAPH
|
||||
//#define MMU_SEGMENTATION_DEBUG_REGIONS
|
||||
//#define MMU_SEGMENTATION_DEBUG_INPUT
|
||||
//#define MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
//#define MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -147,18 +149,6 @@ struct PaintedLineVisitor
|
||||
static inline const double append_threshold2 = Slic3r::sqr(append_threshold);
|
||||
};
|
||||
|
||||
static std::vector<ColoredLine> to_colored_lines(const EdgeGrid::Contour &contour, int color)
|
||||
{
|
||||
std::vector<ColoredLine> lines;
|
||||
if (contour.num_segments() > 2) {
|
||||
lines.reserve(contour.num_segments());
|
||||
for (auto it = contour.begin(); it != contour.end() - 1; ++it)
|
||||
lines.push_back({Line(*it, *(it + 1)), color});
|
||||
lines.push_back({Line(contour.back(), contour.front()), color});
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
static Polygon colored_points_to_polygon(const std::vector<ColoredLine> &lines)
|
||||
{
|
||||
Polygon out;
|
||||
@ -242,25 +232,18 @@ static std::vector<std::vector<std::pair<size_t, size_t>>> get_all_segments(cons
|
||||
return all_segments;
|
||||
}
|
||||
|
||||
static std::vector<ColoredLine> colorize_line(const Line & line_to_process,
|
||||
const size_t start_idx,
|
||||
const size_t end_idx,
|
||||
std::vector<PaintedLine> &painted_lines)
|
||||
static std::vector<PaintedLine> filter_painted_lines(const Line &line_to_process, const size_t start_idx, const size_t end_idx, const std::vector<PaintedLine> &painted_lines)
|
||||
{
|
||||
std::vector<PaintedLine> internal_painted;
|
||||
for (size_t line_idx = start_idx; line_idx <= end_idx; ++line_idx)
|
||||
internal_painted.emplace_back(painted_lines[line_idx]);
|
||||
|
||||
const int filter_eps_value = scale_(0.1f);
|
||||
std::vector<PaintedLine> filtered_lines;
|
||||
filtered_lines.emplace_back(internal_painted.front());
|
||||
for (size_t line_idx = 1; line_idx < internal_painted.size(); ++line_idx) {
|
||||
filtered_lines.emplace_back(painted_lines[start_idx]);
|
||||
for (size_t line_idx = start_idx + 1; line_idx <= end_idx; ++line_idx) {
|
||||
// line_to_process is already all colored. Skip another possible duplicate coloring.
|
||||
if(filtered_lines.back().projected_line.b == line_to_process.b)
|
||||
break;
|
||||
|
||||
PaintedLine &prev = filtered_lines.back();
|
||||
PaintedLine &curr = internal_painted[line_idx];
|
||||
const PaintedLine &curr = painted_lines[line_idx];
|
||||
|
||||
double prev_length = prev.projected_line.length();
|
||||
double curr_dist_start = (curr.projected_line.a - prev.projected_line.a).cast<double>().norm();
|
||||
@ -278,31 +261,84 @@ static std::vector<ColoredLine> colorize_line(const Line & line_to_
|
||||
}
|
||||
} else {
|
||||
double curr_dist_end = (curr.projected_line.b - prev.projected_line.a).cast<double>().norm();
|
||||
if (curr_dist_end <= prev_length) {
|
||||
} else {
|
||||
if (prev.color == curr.color) {
|
||||
if (curr_dist_end > prev_length) {
|
||||
if (prev.color == curr.color)
|
||||
prev.projected_line.b = curr.projected_line.b;
|
||||
} else {
|
||||
curr.projected_line.a = prev.projected_line.b;
|
||||
filtered_lines.emplace_back(curr);
|
||||
}
|
||||
else
|
||||
filtered_lines.push_back({curr.contour_idx, curr.line_idx, Line{prev.projected_line.b, curr.projected_line.b}, curr.color});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ColoredLine> final_lines;
|
||||
double dist_to_start = (filtered_lines.front().projected_line.a - line_to_process.a).cast<double>().norm();
|
||||
if (dist_to_start <= filter_eps_value) {
|
||||
if (double dist_to_start = (filtered_lines.front().projected_line.a - line_to_process.a).cast<double>().norm(); dist_to_start <= filter_eps_value)
|
||||
filtered_lines.front().projected_line.a = line_to_process.a;
|
||||
final_lines.push_back({filtered_lines.front().projected_line, filtered_lines.front().color});
|
||||
} else {
|
||||
final_lines.push_back({Line(line_to_process.a, filtered_lines.front().projected_line.a), 0});
|
||||
final_lines.push_back({filtered_lines.front().projected_line, filtered_lines.front().color});
|
||||
|
||||
if (double dist_to_end = (filtered_lines.back().projected_line.b - line_to_process.b).cast<double>().norm(); dist_to_end <= filter_eps_value)
|
||||
filtered_lines.back().projected_line.b = line_to_process.b;
|
||||
|
||||
return filtered_lines;
|
||||
}
|
||||
|
||||
static std::vector<std::vector<PaintedLine>> post_process_painted_lines(const std::vector<EdgeGrid::Contour> &contours, std::vector<PaintedLine> &&painted_lines)
|
||||
{
|
||||
if (painted_lines.empty())
|
||||
return {};
|
||||
|
||||
auto comp = [&contours](const PaintedLine &first, const PaintedLine &second) {
|
||||
Point first_start_p = contours[first.contour_idx].segment_start(first.line_idx);
|
||||
return first.contour_idx < second.contour_idx ||
|
||||
(first.contour_idx == second.contour_idx &&
|
||||
(first.line_idx < second.line_idx ||
|
||||
(first.line_idx == second.line_idx &&
|
||||
((first.projected_line.a - first_start_p).cast<double>().squaredNorm() < (second.projected_line.a - first_start_p).cast<double>().squaredNorm() ||
|
||||
((first.projected_line.a - first_start_p).cast<double>().squaredNorm() == (second.projected_line.a - first_start_p).cast<double>().squaredNorm() &&
|
||||
(first.projected_line.b - first.projected_line.a).cast<double>().squaredNorm() < (second.projected_line.b - second.projected_line.a).cast<double>().squaredNorm())))));
|
||||
};
|
||||
std::sort(painted_lines.begin(), painted_lines.end(), comp);
|
||||
|
||||
std::vector<std::vector<PaintedLine>> filtered_painted_lines(contours.size());
|
||||
size_t prev_painted_line_idx = 0;
|
||||
for (size_t curr_painted_line_idx = 0; curr_painted_line_idx < painted_lines.size(); ++curr_painted_line_idx) {
|
||||
size_t next_painted_line_idx = curr_painted_line_idx + 1;
|
||||
if (next_painted_line_idx >= painted_lines.size() || painted_lines[curr_painted_line_idx].contour_idx != painted_lines[next_painted_line_idx].contour_idx || painted_lines[curr_painted_line_idx].line_idx != painted_lines[next_painted_line_idx].line_idx) {
|
||||
const PaintedLine &start_line = painted_lines[prev_painted_line_idx];
|
||||
const Line &line_to_process = contours[start_line.contour_idx].get_segment(start_line.line_idx);
|
||||
Slic3r::append(filtered_painted_lines[painted_lines[curr_painted_line_idx].contour_idx], filter_painted_lines(line_to_process, prev_painted_line_idx, curr_painted_line_idx, painted_lines));
|
||||
prev_painted_line_idx = next_painted_line_idx;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t line_idx = 1; line_idx < filtered_lines.size(); ++line_idx) {
|
||||
ColoredLine &prev = final_lines.back();
|
||||
PaintedLine &curr = filtered_lines[line_idx];
|
||||
return filtered_painted_lines;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static bool are_lines_connected(const std::vector<ColoredLine> &colored_lines)
|
||||
{
|
||||
for (size_t line_idx = 1; line_idx < colored_lines.size(); ++line_idx)
|
||||
if (colored_lines[line_idx - 1].line.b != colored_lines[line_idx].line.a)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::vector<ColoredLine> colorize_line(const Line &line_to_process,
|
||||
const size_t start_idx,
|
||||
const size_t end_idx,
|
||||
const std::vector<PaintedLine> &painted_contour)
|
||||
{
|
||||
assert(start_idx < painted_contour.size() && end_idx < painted_contour.size() && start_idx <= end_idx);
|
||||
assert(std::all_of(painted_contour.begin() + start_idx, painted_contour.begin() + end_idx + 1, [&painted_contour, &start_idx](const auto &p_line) { return painted_contour[start_idx].line_idx == p_line.line_idx; }));
|
||||
|
||||
const int filter_eps_value = scale_(0.1f);
|
||||
std::vector<ColoredLine> final_lines;
|
||||
const PaintedLine &first_line = painted_contour[start_idx];
|
||||
if (double dist_to_start = (first_line.projected_line.a - line_to_process.a).cast<double>().norm(); dist_to_start > filter_eps_value)
|
||||
final_lines.push_back({Line(line_to_process.a, first_line.projected_line.a), 0});
|
||||
final_lines.push_back({first_line.projected_line, first_line.color});
|
||||
|
||||
for (size_t line_idx = start_idx + 1; line_idx <= end_idx; ++line_idx) {
|
||||
ColoredLine &prev = final_lines.back();
|
||||
const PaintedLine &curr = painted_contour[line_idx];
|
||||
|
||||
double line_dist = (curr.projected_line.a - prev.line.b).cast<double>().norm();
|
||||
if (line_dist <= filter_eps_value) {
|
||||
@ -318,18 +354,16 @@ static std::vector<ColoredLine> colorize_line(const Line & line_to_
|
||||
}
|
||||
}
|
||||
|
||||
double dist_to_end = (final_lines.back().line.b - line_to_process.b).cast<double>().norm();
|
||||
if (dist_to_end <= filter_eps_value)
|
||||
final_lines.back().line.b = line_to_process.b;
|
||||
else
|
||||
// If there is non-painted space, then inserts line painted by a default color.
|
||||
if (double dist_to_end = (final_lines.back().line.b - line_to_process.b).cast<double>().norm(); dist_to_end > filter_eps_value)
|
||||
final_lines.push_back({Line(final_lines.back().line.b, line_to_process.b), 0});
|
||||
|
||||
for (size_t line_idx = 1; line_idx < final_lines.size(); ++line_idx)
|
||||
assert(final_lines[line_idx - 1].line.b == final_lines[line_idx].line.a);
|
||||
// Make sure all the lines are connected.
|
||||
assert(are_lines_connected(final_lines));
|
||||
|
||||
for (size_t line_idx = 2; line_idx < final_lines.size(); ++line_idx) {
|
||||
const ColoredLine &line_0 = final_lines[line_idx - 2];
|
||||
ColoredLine & line_1 = final_lines[line_idx - 1];
|
||||
ColoredLine &line_1 = final_lines[line_idx - 1];
|
||||
const ColoredLine &line_2 = final_lines[line_idx - 0];
|
||||
|
||||
if (line_0.color == line_2.color && line_0.color != line_1.color)
|
||||
@ -349,52 +383,25 @@ static std::vector<ColoredLine> colorize_line(const Line & line_to_
|
||||
|
||||
final_lines = colored_lines_simple;
|
||||
|
||||
if (final_lines.size() > 1) {
|
||||
if (final_lines.size() > 1)
|
||||
if (final_lines.front().color != final_lines[1].color && final_lines.front().line.length() <= scale_(0.2)) {
|
||||
final_lines[1].line.a = final_lines.front().line.a;
|
||||
final_lines.erase(final_lines.begin());
|
||||
}
|
||||
}
|
||||
|
||||
if (final_lines.size() > 1) {
|
||||
if (final_lines.size() > 1)
|
||||
if (final_lines.back().color != final_lines[final_lines.size() - 2].color && final_lines.back().line.length() <= scale_(0.2)) {
|
||||
final_lines[final_lines.size() - 2].line.b = final_lines.back().line.b;
|
||||
final_lines.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
return final_lines;
|
||||
}
|
||||
|
||||
static std::vector<ColoredLine> colorize_polygon(const EdgeGrid::Contour &contour, const size_t start_idx, const size_t end_idx, std::vector<PaintedLine> &painted_lines)
|
||||
{
|
||||
std::vector<ColoredLine> new_lines;
|
||||
new_lines.reserve(end_idx - start_idx + 1);
|
||||
for (size_t idx = 0; idx < painted_lines[start_idx].line_idx; ++idx)
|
||||
new_lines.emplace_back(ColoredLine{contour.get_segment(idx), 0});
|
||||
|
||||
for (size_t first_idx = start_idx; first_idx <= end_idx; ++first_idx) {
|
||||
size_t second_idx = first_idx;
|
||||
while (second_idx <= end_idx && painted_lines[first_idx].line_idx == painted_lines[second_idx].line_idx) ++second_idx;
|
||||
--second_idx;
|
||||
|
||||
assert(painted_lines[first_idx].line_idx == painted_lines[second_idx].line_idx);
|
||||
std::vector<ColoredLine> lines_c_line = colorize_line(contour.get_segment(painted_lines[first_idx].line_idx), first_idx, second_idx, painted_lines);
|
||||
new_lines.insert(new_lines.end(), lines_c_line.begin(), lines_c_line.end());
|
||||
|
||||
if (second_idx + 1 <= end_idx)
|
||||
for (size_t idx = painted_lines[second_idx].line_idx + 1; idx < painted_lines[second_idx + 1].line_idx; ++idx)
|
||||
new_lines.emplace_back(ColoredLine{contour.get_segment(idx), 0});
|
||||
|
||||
first_idx = second_idx;
|
||||
}
|
||||
|
||||
for (size_t idx = painted_lines[end_idx].line_idx + 1; idx < contour.num_segments(); ++idx)
|
||||
new_lines.emplace_back(ColoredLine{contour.get_segment(idx), 0});
|
||||
|
||||
static std::vector<ColoredLine> filter_colorized_polygon(std::vector<ColoredLine> &&new_lines) {
|
||||
for (size_t line_idx = 2; line_idx < new_lines.size(); ++line_idx) {
|
||||
const ColoredLine &line_0 = new_lines[line_idx - 2];
|
||||
ColoredLine & line_1 = new_lines[line_idx - 1];
|
||||
ColoredLine &line_1 = new_lines[line_idx - 1];
|
||||
const ColoredLine &line_2 = new_lines[line_idx - 0];
|
||||
|
||||
if (line_0.color == line_2.color && line_0.color != line_1.color && line_0.color >= 1) {
|
||||
@ -404,8 +411,8 @@ static std::vector<ColoredLine> colorize_polygon(const EdgeGrid::Contour &contou
|
||||
|
||||
for (size_t line_idx = 3; line_idx < new_lines.size(); ++line_idx) {
|
||||
const ColoredLine &line_0 = new_lines[line_idx - 3];
|
||||
ColoredLine & line_1 = new_lines[line_idx - 2];
|
||||
ColoredLine & line_2 = new_lines[line_idx - 1];
|
||||
ColoredLine &line_1 = new_lines[line_idx - 2];
|
||||
ColoredLine &line_2 = new_lines[line_idx - 1];
|
||||
const ColoredLine &line_3 = new_lines[line_idx - 0];
|
||||
|
||||
if (line_0.color == line_3.color && (line_0.color != line_1.color || line_0.color != line_2.color) && line_0.color >= 1 && line_3.color >= 1) {
|
||||
@ -425,79 +432,110 @@ static std::vector<ColoredLine> colorize_polygon(const EdgeGrid::Contour &contou
|
||||
return total_length;
|
||||
};
|
||||
|
||||
for (size_t pair_idx = 1; pair_idx < segments.size(); ++pair_idx) {
|
||||
int color0 = new_lines[segments[pair_idx - 1].first].color;
|
||||
int color1 = new_lines[segments[pair_idx - 0].first].color;
|
||||
if (segments.size() >= 2)
|
||||
for (size_t curr_idx = 0; curr_idx < segments.size(); ++curr_idx) {
|
||||
size_t next_idx = next_idx_modulo(curr_idx, segments.size());
|
||||
assert(curr_idx != next_idx);
|
||||
|
||||
double seg0l = segment_length(segments[pair_idx - 1]);
|
||||
double seg1l = segment_length(segments[pair_idx - 0]);
|
||||
int color0 = new_lines[segments[curr_idx].first].color;
|
||||
int color1 = new_lines[segments[next_idx].first].color;
|
||||
|
||||
if (color0 != color1 && seg0l >= scale_(0.1) && seg1l <= scale_(0.2)) {
|
||||
for (size_t seg_start_idx = segments[pair_idx].first; seg_start_idx != segments[pair_idx].second; seg_start_idx = (seg_start_idx + 1 < new_lines.size()) ? seg_start_idx + 1 : 0)
|
||||
new_lines[seg_start_idx].color = color0;
|
||||
new_lines[segments[pair_idx].second].color = color0;
|
||||
double seg0l = segment_length(segments[curr_idx]);
|
||||
double seg1l = segment_length(segments[next_idx]);
|
||||
|
||||
if (color0 != color1 && seg0l >= scale_(0.1) && seg1l <= scale_(0.2)) {
|
||||
for (size_t seg_start_idx = segments[next_idx].first; seg_start_idx != segments[next_idx].second; seg_start_idx = (seg_start_idx + 1 < new_lines.size()) ? seg_start_idx + 1 : 0)
|
||||
new_lines[seg_start_idx].color = color0;
|
||||
new_lines[segments[next_idx].second].color = color0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
segments = get_segments(new_lines);
|
||||
for (size_t pair_idx = 1; pair_idx < segments.size(); ++pair_idx) {
|
||||
int color0 = new_lines[segments[pair_idx - 1].first].color;
|
||||
int color1 = new_lines[segments[pair_idx - 0].first].color;
|
||||
double seg1l = segment_length(segments[pair_idx - 0]);
|
||||
if (segments.size() >= 2)
|
||||
for (size_t curr_idx = 0; curr_idx < segments.size(); ++curr_idx) {
|
||||
size_t next_idx = next_idx_modulo(curr_idx, segments.size());
|
||||
assert(curr_idx != next_idx);
|
||||
|
||||
if (color0 >= 1 && color0 != color1 && seg1l <= scale_(0.2)) {
|
||||
for (size_t seg_start_idx = segments[pair_idx].first; seg_start_idx != segments[pair_idx].second; seg_start_idx = (seg_start_idx + 1 < new_lines.size()) ? seg_start_idx + 1 : 0)
|
||||
new_lines[seg_start_idx].color = color0;
|
||||
new_lines[segments[pair_idx].second].color = color0;
|
||||
int color0 = new_lines[segments[curr_idx].first].color;
|
||||
int color1 = new_lines[segments[next_idx].first].color;
|
||||
double seg1l = segment_length(segments[next_idx]);
|
||||
|
||||
if (color0 >= 1 && color0 != color1 && seg1l <= scale_(0.2)) {
|
||||
for (size_t seg_start_idx = segments[next_idx].first; seg_start_idx != segments[next_idx].second; seg_start_idx = (seg_start_idx + 1 < new_lines.size()) ? seg_start_idx + 1 : 0)
|
||||
new_lines[seg_start_idx].color = color0;
|
||||
new_lines[segments[next_idx].second].color = color0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t pair_idx = 2; pair_idx < segments.size(); ++pair_idx) {
|
||||
int color0 = new_lines[segments[pair_idx - 2].first].color;
|
||||
int color1 = new_lines[segments[pair_idx - 1].first].color;
|
||||
int color2 = new_lines[segments[pair_idx - 0].first].color;
|
||||
segments = get_segments(new_lines);
|
||||
if (segments.size() >= 3)
|
||||
for (size_t curr_idx = 0; curr_idx < segments.size(); ++curr_idx) {
|
||||
size_t next_idx = next_idx_modulo(curr_idx, segments.size());
|
||||
size_t next_next_idx = next_idx_modulo(next_idx, segments.size());
|
||||
|
||||
if (color0 > 0 && color0 == color2 && color0 != color1 && segment_length(segments[pair_idx - 1]) <= scale_(0.5)) {
|
||||
for (size_t seg_start_idx = segments[pair_idx].first; seg_start_idx != segments[pair_idx].second; seg_start_idx = (seg_start_idx + 1 < new_lines.size()) ? seg_start_idx + 1 : 0)
|
||||
new_lines[seg_start_idx].color = color0;
|
||||
new_lines[segments[pair_idx].second].color = color0;
|
||||
int color0 = new_lines[segments[curr_idx].first].color;
|
||||
int color1 = new_lines[segments[next_idx].first].color;
|
||||
int color2 = new_lines[segments[next_next_idx].first].color;
|
||||
|
||||
if (color0 > 0 && color0 == color2 && color0 != color1 && segment_length(segments[next_idx]) <= scale_(0.5)) {
|
||||
for (size_t seg_start_idx = segments[next_next_idx].first; seg_start_idx != segments[next_next_idx].second; seg_start_idx = (seg_start_idx + 1 < new_lines.size()) ? seg_start_idx + 1 : 0)
|
||||
new_lines[seg_start_idx].color = color0;
|
||||
new_lines[segments[next_next_idx].second].color = color0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_lines;
|
||||
return std::move(new_lines);
|
||||
}
|
||||
|
||||
static std::vector<std::vector<ColoredLine>> colorize_polygons(const std::vector<EdgeGrid::Contour> &contours, std::vector<PaintedLine> &painted_lines)
|
||||
{
|
||||
const size_t start_idx = 0;
|
||||
const size_t end_idx = painted_lines.size() - 1;
|
||||
static std::vector<ColoredLine> colorize_contour(const EdgeGrid::Contour &contour, const std::vector<PaintedLine> &painted_contour) {
|
||||
assert(painted_contour.empty() || std::all_of(painted_contour.begin(), painted_contour.end(), [&painted_contour](const auto &p_line) { return painted_contour.front().contour_idx == p_line.contour_idx; }));
|
||||
|
||||
std::vector<std::vector<ColoredLine>> new_polygons;
|
||||
new_polygons.reserve(contours.size());
|
||||
|
||||
for (size_t idx = 0; idx < painted_lines[start_idx].contour_idx; ++idx)
|
||||
new_polygons.emplace_back(to_colored_lines(contours[idx], 0));
|
||||
|
||||
for (size_t first_idx = start_idx; first_idx <= end_idx; ++first_idx) {
|
||||
size_t second_idx = first_idx;
|
||||
while (second_idx <= end_idx && painted_lines[first_idx].contour_idx == painted_lines[second_idx].contour_idx)
|
||||
++second_idx;
|
||||
--second_idx;
|
||||
|
||||
assert(painted_lines[first_idx].contour_idx == painted_lines[second_idx].contour_idx);
|
||||
new_polygons.emplace_back(colorize_polygon(contours[painted_lines[first_idx].contour_idx], first_idx, second_idx, painted_lines));
|
||||
|
||||
if (second_idx + 1 <= end_idx)
|
||||
for (size_t idx = painted_lines[second_idx].contour_idx + 1; idx < painted_lines[second_idx + 1].contour_idx; ++idx)
|
||||
new_polygons.emplace_back(to_colored_lines(contours[idx], 0));
|
||||
|
||||
first_idx = second_idx;
|
||||
std::vector<ColoredLine> colorized_contour;
|
||||
if (painted_contour.empty()) {
|
||||
// Appends contour with default color for lines before the first PaintedLine.
|
||||
colorized_contour.reserve(contour.num_segments());
|
||||
for (const Line &line : contour.get_segments())
|
||||
colorized_contour.emplace_back(ColoredLine{line, 0});
|
||||
return colorized_contour;
|
||||
}
|
||||
|
||||
for (size_t idx = painted_lines[end_idx].contour_idx + 1; idx < contours.size(); ++idx)
|
||||
new_polygons.emplace_back(to_colored_lines(contours[idx], 0));
|
||||
colorized_contour.reserve(contour.num_segments() + painted_contour.size());
|
||||
for (size_t idx = 0; idx < painted_contour.front().line_idx; ++idx)
|
||||
colorized_contour.emplace_back(ColoredLine{contour.get_segment(idx), 0});
|
||||
|
||||
return new_polygons;
|
||||
size_t prev_painted_line_idx = 0;
|
||||
for (size_t curr_painted_line_idx = 0; curr_painted_line_idx < painted_contour.size(); ++curr_painted_line_idx) {
|
||||
size_t next_painted_line_idx = curr_painted_line_idx + 1;
|
||||
if (next_painted_line_idx >= painted_contour.size() || painted_contour[curr_painted_line_idx].line_idx != painted_contour[next_painted_line_idx].line_idx) {
|
||||
const std::vector<PaintedLine> &painted_contour_copy = painted_contour;
|
||||
Slic3r::append(colorized_contour, colorize_line(contour.get_segment(painted_contour[prev_painted_line_idx].line_idx), prev_painted_line_idx, curr_painted_line_idx, painted_contour_copy));
|
||||
|
||||
// Appends contour with default color for lines between the current and the next PaintedLine.
|
||||
if (next_painted_line_idx < painted_contour.size())
|
||||
for (size_t idx = painted_contour[curr_painted_line_idx].line_idx + 1; idx < painted_contour[next_painted_line_idx].line_idx; ++idx)
|
||||
colorized_contour.emplace_back(ColoredLine{contour.get_segment(idx), 0});
|
||||
|
||||
prev_painted_line_idx = next_painted_line_idx;
|
||||
}
|
||||
}
|
||||
|
||||
// Appends contour with default color for lines after the last PaintedLine.
|
||||
for (size_t idx = painted_contour.back().line_idx + 1; idx < contour.num_segments(); ++idx)
|
||||
colorized_contour.emplace_back(ColoredLine{contour.get_segment(idx), 0});
|
||||
|
||||
assert(!colorized_contour.empty());
|
||||
return filter_colorized_polygon(std::move(colorized_contour));
|
||||
}
|
||||
|
||||
static std::vector<std::vector<ColoredLine>> colorize_contours(const std::vector<EdgeGrid::Contour> &contours, const std::vector<std::vector<PaintedLine>> &painted_contours)
|
||||
{
|
||||
assert(contours.size() == painted_contours.size());
|
||||
std::vector<std::vector<ColoredLine>> colorized_contours(contours.size());
|
||||
for (const std::vector<PaintedLine> &painted_contour : painted_contours) {
|
||||
size_t contour_idx = &painted_contour - &painted_contours.front();
|
||||
colorized_contours[contour_idx] = colorize_contour(contours[contour_idx], painted_contours[contour_idx]);
|
||||
}
|
||||
return colorized_contours;
|
||||
}
|
||||
|
||||
using boost::polygon::voronoi_diagram;
|
||||
@ -1582,6 +1620,39 @@ void export_processed_input_expolygons_to_svg(const std::string &path, const Lay
|
||||
}
|
||||
#endif // MMU_SEGMENTATION_DEBUG_INPUT
|
||||
|
||||
#ifdef MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
static void export_painted_lines_to_svg(const std::string &path, const std::vector<std::vector<PaintedLine>> &all_painted_lines, const ExPolygons &lslices)
|
||||
{
|
||||
const std::vector<std::string> colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "yellow"};
|
||||
coordf_t stroke_width = scale_(0.05);
|
||||
BoundingBox bbox = get_extents(lslices);
|
||||
bbox.offset(scale_(1.));
|
||||
::Slic3r::SVG svg(path.c_str(), bbox);
|
||||
|
||||
for (const Line &line : to_lines(lslices))
|
||||
svg.draw(line, "green", stroke_width);
|
||||
|
||||
for (const std::vector<PaintedLine> &painted_lines : all_painted_lines)
|
||||
for (const PaintedLine &painted_line : painted_lines)
|
||||
svg.draw(painted_line.projected_line, painted_line.color < int(colors.size()) ? colors[painted_line.color] : "black", stroke_width);
|
||||
}
|
||||
#endif // MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
|
||||
#ifdef MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS
|
||||
static void export_colorized_polygons_to_svg(const std::string &path, const std::vector<std::vector<ColoredLine>> &colorized_polygons, const ExPolygons &lslices)
|
||||
{
|
||||
const std::vector<std::string> colors = {"blue", "cyan", "red", "orange", "magenta", "pink", "purple", "green", "yellow"};
|
||||
coordf_t stroke_width = scale_(0.05);
|
||||
BoundingBox bbox = get_extents(lslices);
|
||||
bbox.offset(scale_(1.));
|
||||
::Slic3r::SVG svg(path.c_str(), bbox);
|
||||
|
||||
for (const std::vector<ColoredLine> &colorized_polygon : colorized_polygons)
|
||||
for (const ColoredLine &colorized_line : colorized_polygon)
|
||||
svg.draw(colorized_line.line, colorized_line.color < int(colors.size())? colors[colorized_line.color] : "black", stroke_width);
|
||||
}
|
||||
#endif // MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS
|
||||
|
||||
// Check if all ColoredLine representing a single layer uses the same color.
|
||||
static bool has_layer_only_one_color(const std::vector<std::vector<ColoredLine>> &colored_polygons)
|
||||
{
|
||||
@ -1731,22 +1802,32 @@ std::vector<std::vector<std::pair<ExPolygon, size_t>>> multi_material_segmentati
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, print_object.layers().size()), [&edge_grids, &input_expolygons, &painted_lines, &segmented_regions, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||
throw_on_cancel_callback();
|
||||
auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) {
|
||||
Point first_start_p = edge_grids[layer_idx].contours()[first.contour_idx].segment_start(first.line_idx);
|
||||
return first.contour_idx < second.contour_idx ||
|
||||
(first.contour_idx == second.contour_idx &&
|
||||
(first.line_idx < second.line_idx ||
|
||||
(first.line_idx == second.line_idx &&
|
||||
((first.projected_line.a - first_start_p).cast<double>().squaredNorm() < (second.projected_line.a - first_start_p).cast<double>().squaredNorm() ||
|
||||
((first.projected_line.a - first_start_p).cast<double>().squaredNorm() == (second.projected_line.a - first_start_p).cast<double>().squaredNorm() &&
|
||||
(first.projected_line.b - first.projected_line.a).cast<double>().squaredNorm() < (second.projected_line.b - second.projected_line.a).cast<double>().squaredNorm())))));
|
||||
};
|
||||
if (!painted_lines[layer_idx].empty()) {
|
||||
#ifdef MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
{
|
||||
static int iRun = 0;
|
||||
export_painted_lines_to_svg(debug_out_path("mm-painted-lines-%d-%d.svg", layer_idx, iRun++), {painted_lines[layer_idx]}, input_expolygons[layer_idx]);
|
||||
}
|
||||
#endif // MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
|
||||
std::sort(painted_lines[layer_idx].begin(), painted_lines[layer_idx].end(), comp);
|
||||
std::vector<PaintedLine> &painted_lines_single = painted_lines[layer_idx];
|
||||
std::vector<std::vector<PaintedLine>> post_processed_painted_lines = post_process_painted_lines(edge_grids[layer_idx].contours(), std::move(painted_lines[layer_idx]));
|
||||
|
||||
#ifdef MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
{
|
||||
static int iRun = 0;
|
||||
export_painted_lines_to_svg(debug_out_path("mm-painted-lines-post-processed-%d-%d.svg", layer_idx, iRun++), post_processed_painted_lines, input_expolygons[layer_idx]);
|
||||
}
|
||||
#endif // MMU_SEGMENTATION_DEBUG_PAINTED_LINES
|
||||
|
||||
std::vector<std::vector<ColoredLine>> color_poly = colorize_contours(edge_grids[layer_idx].contours(), post_processed_painted_lines);
|
||||
|
||||
#ifdef MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS
|
||||
{
|
||||
static int iRun = 0;
|
||||
export_colorized_polygons_to_svg(debug_out_path("mm-colorized_polygons-%d-%d.svg", layer_idx, iRun++), color_poly, input_expolygons[layer_idx]);
|
||||
}
|
||||
#endif // MMU_SEGMENTATION_DEBUG_COLORIZED_POLYGONS
|
||||
|
||||
if (!painted_lines_single.empty()) {
|
||||
std::vector<std::vector<ColoredLine>> color_poly = colorize_polygons(edge_grids[layer_idx].contours(), painted_lines_single);
|
||||
assert(!color_poly.empty());
|
||||
assert(!color_poly.front().empty());
|
||||
if (has_layer_only_one_color(color_poly)) {
|
||||
|
Loading…
Reference in New Issue
Block a user