Fixed the orientation of ExtrusionLoops when Arachne is used.

This commit is contained in:
Lukáš Hejl 2022-06-15 23:24:43 +02:00
parent 2d7d8ba2f6
commit f34c1f14da
4 changed files with 51 additions and 7 deletions

View file

@ -18,6 +18,8 @@
#include <boost/log/trivial.hpp>
//#define ARACHNE_STITCH_PATCH_DEBUG
namespace Slic3r::Arachne
{
@ -549,7 +551,7 @@ void WallToolPaths::stitchToolPaths(std::vector<VariableWidthLines> &toolpaths,
VariableWidthLines stitched_polylines;
VariableWidthLines closed_polygons;
PolylineStitcher<VariableWidthLines, ExtrusionLine, ExtrusionJunction>::stitch(wall_lines, stitched_polylines, closed_polygons, stitch_distance);
#ifdef DEBUG
#ifdef ARACHNE_STITCH_PATCH_DEBUG
for (const ExtrusionLine& line : stitched_polylines) {
if ( ! line.is_odd && line.polylineLength() > 3 * stitch_distance && line.size() > 3) {
BOOST_LOG_TRIVIAL(error) << "Some even contour lines could not be closed into polygons!";
@ -608,7 +610,7 @@ void WallToolPaths::stitchToolPaths(std::vector<VariableWidthLines> &toolpaths,
}
}
}
#endif // DEBUG
#endif // ARACHNE_STITCH_PATCH_DEBUG
wall_lines = stitched_polylines; // replace input toolpaths with stitched polylines
for (ExtrusionLine& wall_polygon : closed_polygons)

View file

@ -232,6 +232,35 @@ int64_t ExtrusionLine::calculateExtrusionAreaDeviationError(ExtrusionJunction A,
}
}
bool ExtrusionLine::is_contour() const
{
if (!this->is_closed)
return false;
Polygon poly;
poly.points.reserve(this->junctions.size());
for (const ExtrusionJunction &junction : this->junctions)
poly.points.emplace_back(junction.p);
// Arachne produces contour with clockwise orientation and holes with counterclockwise orientation.
return poly.is_clockwise();
}
double ExtrusionLine::area() const
{
assert(this->is_closed);
double a = 0.;
if (this->junctions.size() >= 3) {
Vec2d p1 = this->junctions.back().p.cast<double>();
for (const ExtrusionJunction &junction : this->junctions) {
Vec2d p2 = junction.p.cast<double>();
a += cross2(p1, p2);
p1 = p2;
}
}
return 0.5 * a;
}
} // namespace Slic3r::Arachne
namespace Slic3r {

View file

@ -189,6 +189,10 @@ struct ExtrusionLine
* \param weighted_average_width The weighted average of the widths of the two colinear extrusion segments
* */
static int64_t calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C, coord_t& weighted_average_width);
bool is_contour() const;
double area() const;
};
static inline Slic3r::ThickPolyline to_thick_polyline(const Arachne::ExtrusionLine &line_junctions)

View file

@ -354,6 +354,8 @@ static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Path &subject, con
struct PerimeterGeneratorArachneExtrusion
{
Arachne::ExtrusionLine *extrusion = nullptr;
// Indicates if closed ExtrusionLine is a contour or a hole. Used it only when ExtrusionLine is a closed loop.
bool is_contour = false;
// Should this extrusion be fuzzyfied on path generation?
bool fuzzify = false;
};
@ -414,11 +416,18 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
// Append paths to collection.
if (!paths.empty()) {
if (extrusion->is_closed)
extrusion_coll.entities.emplace_back(new ExtrusionLoop(std::move(paths)));
else
if (extrusion->is_closed) {
ExtrusionLoop extrusion_loop(std::move(paths));
// Restore the orientation of the extrusion loop.
if (pg_extrusion.is_contour)
extrusion_loop.make_counter_clockwise();
else
extrusion_loop.make_clockwise();
extrusion_coll.append(std::move(extrusion_loop));
} else
for (ExtrusionPath &path : paths)
extrusion_coll.entities.emplace_back(new ExtrusionPath(std::move(path)));
extrusion_coll.append(ExtrusionPath(std::move(path)));
}
}
@ -541,7 +550,7 @@ void PerimeterGenerator::process_arachne()
}
auto &best_path = all_extrusions[best_candidate];
ordered_extrusions.push_back({best_path, false});
ordered_extrusions.push_back({best_path, best_path->is_contour(), false});
processed[best_candidate] = true;
for (size_t unlocked_idx : blocking[best_candidate])
blocked[unlocked_idx]--;