mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-19 12:47:50 -06:00
Fixed crash in Adaptive Cubic infill if just a single line was extracted.
New function to chain lines, however not used by the Adaptive Cubic infill.
This commit is contained in:
parent
73d8bab4f8
commit
6cdb19971f
3 changed files with 66 additions and 63 deletions
|
@ -361,8 +361,8 @@ static bool verify_traversal_order(
|
||||||
c[1] - c[0], c[2] - c[0], c[3] - c[1], c[3] - c[2], c[3] - c[0],
|
c[1] - c[0], c[2] - c[0], c[3] - c[1], c[3] - c[2], c[3] - c[0],
|
||||||
c[5] - c[4], c[6] - c[4], c[7] - c[5], c[7] - c[6], c[7] - c[4]
|
c[5] - c[4], c[6] - c[4], c[7] - c[5], c[7] - c[6], c[7] - c[4]
|
||||||
};
|
};
|
||||||
assert(std::abs(dirs[4].z()) < 0.001);
|
assert(std::abs(dirs[4].z()) < 0.005);
|
||||||
assert(std::abs(dirs[9].z()) < 0.001);
|
assert(std::abs(dirs[9].z()) < 0.005);
|
||||||
assert(dirs[0].isApprox(dirs[3]));
|
assert(dirs[0].isApprox(dirs[3]));
|
||||||
assert(dirs[1].isApprox(dirs[2]));
|
assert(dirs[1].isApprox(dirs[2]));
|
||||||
assert(dirs[5].isApprox(dirs[8]));
|
assert(dirs[5].isApprox(dirs[8]));
|
||||||
|
@ -413,7 +413,7 @@ static void generate_infill_lines_recursive(
|
||||||
Line new_line(Point::new_scale(from), Point::new_scale(to));
|
Line new_line(Point::new_scale(from), Point::new_scale(to));
|
||||||
if (last_line.a.x() == std::numeric_limits<coord_t>::max()) {
|
if (last_line.a.x() == std::numeric_limits<coord_t>::max()) {
|
||||||
last_line.a = new_line.a;
|
last_line.a = new_line.a;
|
||||||
} else if ((new_line.a - last_line.b).cwiseAbs().maxCoeff() > 300) { // SCALED_EPSILON is 100 and it is not enough) {
|
} else if ((new_line.a - last_line.b).cwiseAbs().maxCoeff() > 300) { // SCALED_EPSILON is 100 and it is not enough
|
||||||
context.output_lines.emplace_back(last_line);
|
context.output_lines.emplace_back(last_line);
|
||||||
last_line.a = new_line.a;
|
last_line.a = new_line.a;
|
||||||
}
|
}
|
||||||
|
@ -434,64 +434,6 @@ static void generate_infill_lines_recursive(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Collect the line segments.
|
|
||||||
static Polylines chain_lines(const std::vector<Line> &lines, const double point_distance_epsilon)
|
|
||||||
{
|
|
||||||
// Create line end point lookup.
|
|
||||||
struct LineEnd {
|
|
||||||
LineEnd(Line *line, bool start) : line(line), start(start) {}
|
|
||||||
Line *line;
|
|
||||||
// Is it the start or end point?
|
|
||||||
bool start;
|
|
||||||
const Point& point() const { return start ? line->a : line->b; }
|
|
||||||
const Point& other_point() const { return start ? line->b : line->a; }
|
|
||||||
LineEnd other_end() const { return LineEnd(line, ! start); }
|
|
||||||
bool operator==(const LineEnd &rhs) const { return this->line == rhs.line && this->start == rhs.start; }
|
|
||||||
};
|
|
||||||
struct LineEndAccessor {
|
|
||||||
const Point* operator()(const LineEnd &pt) const { return &pt.point(); }
|
|
||||||
};
|
|
||||||
typedef ClosestPointInRadiusLookup<LineEnd, LineEndAccessor> ClosestPointLookupType;
|
|
||||||
ClosestPointLookupType closest_end_point_lookup(point_distance_epsilon);
|
|
||||||
for (const Line &line : lines) {
|
|
||||||
closest_end_point_lookup.insert(LineEnd(&line, true));
|
|
||||||
closest_end_point_lookup.insert(LineEnd(&line, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chain the lines.
|
|
||||||
std::vector<char> line_consumed(lines.size(), false);
|
|
||||||
static const double point_distance_epsilon2 = point_distance_epsilon * point_distance_epsilon;
|
|
||||||
Polylines out;
|
|
||||||
for (const Line &seed : lines)
|
|
||||||
if (! line_consumed[&seed - lines.data()]) {
|
|
||||||
line_consumed[&seed - lines.data()] = true;
|
|
||||||
closest_end_point_lookup.erase(LineEnd(&seed, false));
|
|
||||||
closest_end_point_lookup.erase(LineEnd(&seed, true));
|
|
||||||
Polyline pl { seed.a, seed.b };
|
|
||||||
for (size_t round = 0; round < 2; ++ round) {
|
|
||||||
for (;;) {
|
|
||||||
auto [line_end, dist2] = closest_end_point_lookup.find(pl.last_point());
|
|
||||||
if (line_end == nullptr || dist2 >= point_distance_epsilon2)
|
|
||||||
// Cannot extent in this direction.
|
|
||||||
break;
|
|
||||||
// Average the last point.
|
|
||||||
pl.points.back() = 0.5 * (pl.points.back() + line_end->point());
|
|
||||||
// and extend with the new line segment.
|
|
||||||
pl.points.emplace_back(line_end->other_point());
|
|
||||||
closest_end_point_lookup.erase(line_end);
|
|
||||||
closest_end_point_lookup.erase(line_end->other_end());
|
|
||||||
line_consumed[line_end->line - lines.data()] = true;
|
|
||||||
}
|
|
||||||
// reverse and try the oter direction.
|
|
||||||
pl.reverse();
|
|
||||||
}
|
|
||||||
out.emplace_back(std::move(pl));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// #define ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
// #define ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT
|
||||||
#endif
|
#endif
|
||||||
|
@ -574,10 +516,14 @@ void Filler::_fill_surface_single(
|
||||||
if (line.a.x() != std::numeric_limits<coord_t>::max())
|
if (line.a.x() != std::numeric_limits<coord_t>::max())
|
||||||
lines.emplace_back(line);
|
lines.emplace_back(line);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
// Chain touching line segments, convert lines to polylines.
|
||||||
|
//all_polylines = chain_lines(lines, 300.); // SCALED_EPSILON is 100 and it is not enough
|
||||||
|
#else
|
||||||
// Convert lines to polylines.
|
// Convert lines to polylines.
|
||||||
//FIXME chain the lines
|
|
||||||
all_polylines.reserve(lines.size());
|
all_polylines.reserve(lines.size());
|
||||||
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
|
std::transform(lines.begin(), lines.end(), std::back_inserter(all_polylines), [](const Line& l) { return Polyline{ l.a, l.b }; });
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crop all polylines
|
// Crop all polylines
|
||||||
|
@ -590,7 +536,7 @@ void Filler::_fill_surface_single(
|
||||||
}
|
}
|
||||||
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
#endif /* ADAPTIVE_CUBIC_INFILL_DEBUG_OUTPUT */
|
||||||
|
|
||||||
if (params.dont_connect)
|
if (params.dont_connect || all_polylines.size() <= 1)
|
||||||
append(polylines_out, std::move(all_polylines));
|
append(polylines_out, std::move(all_polylines));
|
||||||
else
|
else
|
||||||
connect_infill(chain_polylines(std::move(all_polylines)), expolygon, polylines_out, this->spacing, params);
|
connect_infill(chain_polylines(std::move(all_polylines)), expolygon, polylines_out, this->spacing, params);
|
||||||
|
|
|
@ -1973,4 +1973,59 @@ std::vector<const PrintInstance*> chain_print_object_instances(const Print &prin
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Polylines chain_lines(const std::vector<Line> &lines, const double point_distance_epsilon)
|
||||||
|
{
|
||||||
|
// Create line end point lookup.
|
||||||
|
struct LineEnd {
|
||||||
|
LineEnd(const Line *line, bool start) : line(line), start(start) {}
|
||||||
|
const Line *line;
|
||||||
|
// Is it the start or end point?
|
||||||
|
bool start;
|
||||||
|
const Point& point() const { return start ? line->a : line->b; }
|
||||||
|
const Point& other_point() const { return start ? line->b : line->a; }
|
||||||
|
LineEnd other_end() const { return LineEnd(line, ! start); }
|
||||||
|
bool operator==(const LineEnd &rhs) const { return this->line == rhs.line && this->start == rhs.start; }
|
||||||
|
};
|
||||||
|
struct LineEndAccessor {
|
||||||
|
const Point* operator()(const LineEnd &pt) const { return &pt.point(); }
|
||||||
|
};
|
||||||
|
typedef ClosestPointInRadiusLookup<LineEnd, LineEndAccessor> ClosestPointLookupType;
|
||||||
|
ClosestPointLookupType closest_end_point_lookup(point_distance_epsilon);
|
||||||
|
for (const Line &line : lines) {
|
||||||
|
closest_end_point_lookup.insert(LineEnd(&line, true));
|
||||||
|
closest_end_point_lookup.insert(LineEnd(&line, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chain the lines.
|
||||||
|
std::vector<char> line_consumed(lines.size(), false);
|
||||||
|
static const double point_distance_epsilon2 = point_distance_epsilon * point_distance_epsilon;
|
||||||
|
Polylines out;
|
||||||
|
for (const Line &seed : lines)
|
||||||
|
if (! line_consumed[&seed - lines.data()]) {
|
||||||
|
line_consumed[&seed - lines.data()] = true;
|
||||||
|
closest_end_point_lookup.erase(LineEnd(&seed, false));
|
||||||
|
closest_end_point_lookup.erase(LineEnd(&seed, true));
|
||||||
|
Polyline pl { seed.a, seed.b };
|
||||||
|
for (size_t round = 0; round < 2; ++ round) {
|
||||||
|
for (;;) {
|
||||||
|
auto [line_end, dist2] = closest_end_point_lookup.find(pl.last_point());
|
||||||
|
if (line_end == nullptr || dist2 >= point_distance_epsilon2)
|
||||||
|
// Cannot extent in this direction.
|
||||||
|
break;
|
||||||
|
// Average the last point.
|
||||||
|
pl.points.back() = (0.5 * (pl.points.back().cast<double>() + line_end->point().cast<double>())).cast<coord_t>();
|
||||||
|
// and extend with the new line segment.
|
||||||
|
pl.points.emplace_back(line_end->other_point());
|
||||||
|
closest_end_point_lookup.erase(*line_end);
|
||||||
|
closest_end_point_lookup.erase(line_end->other_end());
|
||||||
|
line_consumed[line_end->line - lines.data()] = true;
|
||||||
|
}
|
||||||
|
// reverse and try the oter direction.
|
||||||
|
pl.reverse();
|
||||||
|
}
|
||||||
|
out.emplace_back(std::move(pl));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -33,6 +33,8 @@ class Print;
|
||||||
struct PrintInstance;
|
struct PrintInstance;
|
||||||
std::vector<const PrintInstance*> chain_print_object_instances(const Print &print);
|
std::vector<const PrintInstance*> chain_print_object_instances(const Print &print);
|
||||||
|
|
||||||
|
// Chain lines into polylines.
|
||||||
|
Polylines chain_lines(const std::vector<Line> &lines, const double point_distance_epsilon);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue