Fixed crossing perimeters in some cases

This commit is contained in:
Lukáš Hejl 2020-10-14 01:02:39 +02:00
parent 556c212f9d
commit 69658a57d8
2 changed files with 29 additions and 22 deletions

View file

@ -356,29 +356,38 @@ namespace Slic3r {
return final_boundary;
}
static Vec2d get_polygon_vertex_inward_normal(const Polygon &polygon, const size_t point_idx)
static Vec2d three_points_inward_normal(const Point &left, const Point &middle, const Point &right)
{
const Point &p0 = polygon.points[(point_idx <= 0) ? (polygon.size() - 1) : (point_idx - 1)];
const Point &p1 = polygon.points[point_idx];
const Point &p2 = polygon.points[(point_idx >= (polygon.size() - 1)) ? (0) : (point_idx + 1)];
assert(left != middle);
assert(middle != right);
assert(p0 != p1);
assert(p1 != p2);
Vec2d normal_1(-1 * (p1.y() - p0.y()), p1.x() - p0.x());
Vec2d normal_2(-1 * (p2.y() - p1.y()), p2.x() - p1.x());
Vec2d normal_1(-1 * (middle.y() - left.y()), middle.x() - left.x());
Vec2d normal_2(-1 * (right.y() - middle.y()), right.x() - middle.x());
normal_1.normalize();
normal_2.normalize();
return (normal_1 + normal_2).normalized();
};
static Vec2d get_polygon_vertex_inward_normal(const Polygon &polygon, const size_t point_idx)
{
const Point &p0 = polygon.points[(point_idx <= 0) ? (polygon.size() - 1) : (point_idx - 1)];
const Point &p1 = polygon.points[point_idx];
const Point &p2 = polygon.points[(point_idx >= (polygon.size() - 1)) ? (0) : (point_idx + 1)];
return three_points_inward_normal(p0, p1, p2);
};
// Compute offset of polygon's in a direction inward normal
static Point get_polygon_vertex_offset(const Polygon &polygon, const size_t point_idx, const int offset)
{
return polygon.points[point_idx] + (get_polygon_vertex_inward_normal(polygon, point_idx) * double(offset)).cast<coord_t>();
}
static Point get_middle_point_offset(const Point &left, const Point &middle, const Point &right, const int offset)
{
return middle + (three_points_inward_normal(left, middle, right) * double(offset)).cast<coord_t>();
}
Polyline AvoidCrossingPerimeters2::travel_to(const GCode &gcodegen, const Point &point)
{
bool use_external = this->use_external_mp || this->use_external_mp_once;
@ -393,7 +402,6 @@ namespace Slic3r {
const Point &end = point;
const Point direction = end - start;
Matrix2d transform_to_x_axis = rotation_by_direction(direction);
Matrix2d transform_from_x_axis = transform_to_x_axis.transpose();
const Line travel_line_orig(start, end);
const Line travel_line((transform_to_x_axis * start.cast<double>()).cast<coord_t>(),
@ -423,7 +431,7 @@ namespace Slic3r {
if (travel_line.intersection(Line(segment.first, segment.second), &intersection_point) &&
intersection_set.find(*it_contour_and_segment) == intersection_set.end()) {
intersections.emplace_back(it_contour_and_segment->first, it_contour_and_segment->second,
(transform_to_x_axis * intersection_point.cast<double>()).cast<coord_t>());
(transform_to_x_axis * intersection_point.cast<double>()).cast<coord_t>(), intersection_point);
intersection_set.insert(*it_contour_and_segment);
}
}
@ -447,19 +455,17 @@ namespace Slic3r {
result.append(start);
for (auto it_first = intersections.begin(); it_first != intersections.end(); ++it_first) {
const Intersection &intersection_first = *it_first;
Point intersection_first_point((transform_from_x_axis * intersection_first.point.cast<double>()).cast<coord_t>());
for (auto it_second = it_first + 1; it_second != intersections.end(); ++it_second) {
const Intersection &intersection_second = *it_second;
Point intersection_second_point((transform_from_x_axis * intersection_second.point.cast<double>()).cast<coord_t>());
if (intersection_first.border_idx == intersection_second.border_idx) {
Lines border_lines = m_boundaries[intersection_first.border_idx].lines();
const Line &first_intersected_line = border_lines[intersection_first.line_idx];
const Line &second_intersected_line = border_lines[intersection_second.line_idx];
// Append the nearest intersection into the path
result.append(intersection_first_point);
result.append(get_middle_point_offset(first_intersected_line.a, intersection_first.point, first_intersected_line.b, SCALED_EPSILON));
Direction shortest_direction = get_shortest_direction(border_lines, intersection_first.line_idx, intersection_second.line_idx,
intersection_first_point, intersection_second_point);
intersection_first.point, intersection_second.point);
// Append the path around the border into the path
// Offset of the polygon's point is used to simplify calculation of intersection between boundary
if (shortest_direction == Direction::Forward)
@ -473,9 +479,9 @@ namespace Slic3r {
result.append(get_polygon_vertex_offset(m_boundaries[intersection_first.border_idx], line_idx + 0, SCALED_EPSILON));
// Append the farthest intersection into the path
result.append(intersection_second_point);
result.append(get_middle_point_offset(second_intersected_line.a, intersection_second.point, second_intersected_line.b, SCALED_EPSILON));
// Skip intersections in between
it_first = it_second;
it_first = (it_second - 1);
break;
}
}

View file

@ -69,12 +69,13 @@ protected:
{
size_t border_idx;
size_t line_idx;
Point point_transformed;
Point point;
Intersection(size_t border_idx, size_t line_idx, Point point)
: border_idx(border_idx), line_idx(line_idx), point(point){};
Intersection(size_t border_idx, size_t line_idx, const Point &point_transformed, const Point &point)
: border_idx(border_idx), line_idx(line_idx), point_transformed(point_transformed), point(point){};
inline bool operator<(const Intersection &other) const { return this->point.x() < other.point.x(); }
inline bool operator<(const Intersection &other) const { return this->point_transformed.x() < other.point_transformed.x(); }
};
enum class Direction { Forward, Backward };