mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-12 02:49:04 +08:00
SPE-2597: Fix clipping logic for clipping arcs with negative radius.
When we are clipping the arc with a negative radius (we are taking the longer angle here), we have to check if we still need to take the longer angle after clipping. Otherwise, we must flip the radius sign to take the shorter angle.
This commit is contained in:
parent
7345da2fa7
commit
fc0feed553
@ -739,10 +739,17 @@ double clip_end(Path &path, double distance)
|
||||
// Rotate the segment end point in reverse towards the start point.
|
||||
if (last.ccw())
|
||||
angle *= -1.;
|
||||
path.push_back({
|
||||
last.point.rotated(angle * (distance / len),
|
||||
arc_center(path.back().point.cast<double>(), last.point.cast<double>(), double(last.radius), last.ccw()).cast<coord_t>()),
|
||||
last.radius, last.orientation });
|
||||
|
||||
const double rotate_by_angle = angle * (distance / len);
|
||||
|
||||
// When we are clipping the arc with a negative radius (we are taking the longer angle here),
|
||||
// we have to check if we still need to take the longer angle after clipping.
|
||||
// Otherwise, we must flip the radius sign to take the shorter angle.
|
||||
const bool flip_radius_sign = last.radius < 0 && std::abs(angle) > M_PI && std::abs(angle - rotate_by_angle) <= M_PI;
|
||||
|
||||
path.push_back({last.point.rotated(rotate_by_angle, arc_center(path.back().point.cast<double>(), last.point.cast<double>(), double(last.radius), last.ccw()).cast<coord_t>()),
|
||||
(flip_radius_sign ? -last.radius : last.radius), last.orientation});
|
||||
|
||||
// Length to go is zero.
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <random>
|
||||
|
||||
#include <libslic3r/ExtrusionEntity.hpp>
|
||||
#include <libslic3r/GCode/ExtrusionOrder.hpp>
|
||||
#include <libslic3r/GCode/SmoothPath.hpp>
|
||||
#include <libslic3r/Geometry/ArcWelder.hpp>
|
||||
#include <libslic3r/Geometry/Circle.hpp>
|
||||
@ -470,6 +471,52 @@ TEST_CASE("ExtrusionMultiPath simplification", "[ArcWelderMultiPathSimplify][!ma
|
||||
REQUIRE(min_segment_length >= resolution);
|
||||
}
|
||||
|
||||
TEST_CASE("SmoothPath clipping test", "[ArcWelder]") {
|
||||
using namespace Slic3r::Geometry;
|
||||
|
||||
const Polyline polyline = {
|
||||
Point(9237362, -279099), Point(9239309, -204770), Point(9232158, 477899), Point(9153712, 1292530),
|
||||
Point(9014384, 2036579), Point(8842322, 2697128), Point(8569131, 3468590), Point(8287136, 4090253),
|
||||
Point(8050736, 4537759), Point(7786167, 4978071), Point(7502123, 5396751), Point(7085512, 5937730),
|
||||
Point(6536631, 6536722), Point(5937701, 7085536), Point(5336389, 7545178), Point(4766354, 7921046),
|
||||
Point(4287299, 8181151), Point(3798566, 8424823), Point(3161891, 8687141), Point(2477384, 8903260),
|
||||
Point(1985727, 9025657), Point(1488659, 9120891), Point(811611, 9208824), Point(229795, 9234222),
|
||||
Point(-477899, 9232158), Point(-1292541, 9153710), Point(-1963942, 9030487), Point(-2483966, 8901437),
|
||||
Point(-2967612, 8752145), Point(-3606656, 8511944), Point(-4098726, 8277235), Point(-4583048, 8025111),
|
||||
Point(-5164553, 7667365), Point(-5602853, 7343037), Point(-6030084, 7003203), Point(-6532687, 6541035),
|
||||
Point(-7085558, 5937673), Point(-7502041, 5396860), Point(-7802209, 4952884), Point(-8061668, 4518435),
|
||||
Point(-8375899, 3912214), Point(-8689042, 3156205), Point(-8915304, 2433948), Point(-9073554, 1769674),
|
||||
Point(-9194504, 960323), Point(-9238723, 227049), Point(-9237360, -279112), Point(-9194498, -960380),
|
||||
Point(-9073524, -1769810), Point(-8895452, -2505523), Point(-8689032, -3156238), Point(-8375859, -3912298),
|
||||
Point(-8025112, -4583044), Point(-7667378, -5164532), Point(-7180536, -5822455), Point(-6729193, -6334406),
|
||||
Point(-6350620, -6713810), Point(-5973693, -7051366), Point(-5438560, -7475505), Point(-4756170, -7927163),
|
||||
Point(-4110103, -8277232), Point(-3651006, -8489813), Point(-3015355, -8738921), Point(-2492584, -8893770),
|
||||
Point(-1963947, -9030483), Point(-1286636, -9154696), Point(-590411, -9222659), Point(14602, -9244383),
|
||||
Point(974789, -9192915), Point(1634833, -9095889), Point(2193590, -8977466), Point(2851102, -8793883),
|
||||
Point(3612042, -8509372), Point(4098709, -8277242), Point(4583076, -8025095), Point(5164577, -7667349),
|
||||
Point(5822437, -7180551), Point(6388368, -6677987), Point(6866030, -6190211), Point(7236430, -5740880),
|
||||
Point(7660739, -5174380), Point(8088357, -4476558), Point(8394013, -3866175), Point(8593000, -3400880),
|
||||
Point(8768650, -2918284), Point(8915319, -2433894), Point(9073549, -1769711), Point(9194508, -960282),
|
||||
Point(9237362, -279099)
|
||||
};
|
||||
|
||||
const ExtrusionAttributes extrusion_attributes(ExtrusionRole::Perimeter, ExtrusionFlow{1.0, 1.0, 1.0});
|
||||
const GCode::SmoothPath smooth_path = {GCode::SmoothPathElement{extrusion_attributes, ArcWelder::fit_path(polyline.points, 32000., 0.05)}};
|
||||
const double smooth_path_length = GCode::length(smooth_path);
|
||||
|
||||
const size_t clip_segment_cnt = 20;
|
||||
for (size_t segment_idx = 1; segment_idx <= clip_segment_cnt; ++segment_idx) {
|
||||
const double clip_length = static_cast<double>(segment_idx) * (smooth_path_length / (clip_segment_cnt + 1));
|
||||
GCode::SmoothPath smooth_path_clipped = smooth_path;
|
||||
|
||||
clip_end(smooth_path_clipped, smooth_path_length - clip_length, scaled<double>(GCode::ExtrusionOrder::min_gcode_segment_length));
|
||||
|
||||
const double smooth_path_clipped_length = GCode::length(smooth_path_clipped);
|
||||
const double relative_diff = std::abs(1. - (clip_length / smooth_path_clipped_length));
|
||||
REQUIRE(relative_diff <= 0.000001);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// For quantization
|
||||
//#include <libslic3r/GCode/GCodeWriter.hpp>
|
||||
|
Loading…
x
Reference in New Issue
Block a user