mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 02:05:58 +08:00
Merge branch 'lh_fix_arcwelder_travel'
This commit is contained in:
commit
a697ca8f12
@ -31,75 +31,46 @@ std::optional<Point> sample_path_point_at_distance_from_start(const SmoothPath &
|
||||
{
|
||||
if (distance >= 0) {
|
||||
for (const SmoothPathElement &el : path) {
|
||||
auto it = el.path.begin();
|
||||
auto end = el.path.end();
|
||||
Point prev_point = it->point;
|
||||
for (++ it; it != end; ++ it) {
|
||||
Point point = it->point;
|
||||
if (it->linear()) {
|
||||
Point prev_point = el.path.front().point;
|
||||
for (auto segment_it = el.path.begin() + 1; segment_it != el.path.end(); ++segment_it) {
|
||||
Point point = segment_it->point;
|
||||
if (segment_it->linear()) {
|
||||
// Linear segment
|
||||
Vec2d v = (point - prev_point).cast<double>();
|
||||
double lsqr = v.squaredNorm();
|
||||
const Vec2d v = (point - prev_point).cast<double>();
|
||||
const double lsqr = v.squaredNorm();
|
||||
if (lsqr > sqr(distance))
|
||||
return std::make_optional<Point>(prev_point + (v * (distance / sqrt(lsqr))).cast<coord_t>());
|
||||
return prev_point + (v * (distance / sqrt(lsqr))).cast<coord_t>();
|
||||
distance -= sqrt(lsqr);
|
||||
} else {
|
||||
// Circular segment
|
||||
float angle = Geometry::ArcWelder::arc_angle(prev_point.cast<float>(), point.cast<float>(), it->radius);
|
||||
double len = std::abs(it->radius) * angle;
|
||||
const float angle = Geometry::ArcWelder::arc_angle(prev_point.cast<float>(), point.cast<float>(), segment_it->radius);
|
||||
const double len = std::abs(segment_it->radius) * angle;
|
||||
if (len > distance) {
|
||||
// Rotate the segment end point in reverse towards the start point.
|
||||
return std::make_optional<Point>(prev_point.rotated(- angle * (distance / len),
|
||||
Geometry::ArcWelder::arc_center(prev_point.cast<float>(), point.cast<float>(), it->radius, it->ccw()).cast<coord_t>()));
|
||||
const Point center_pt = Geometry::ArcWelder::arc_center(prev_point.cast<float>(), point.cast<float>(), segment_it->radius, segment_it->ccw()).cast<coord_t>();
|
||||
const float rotation_dir = (segment_it->ccw() ? 1.f : -1.f);
|
||||
// Rotate the segment start point based on the arc orientation.
|
||||
return prev_point.rotated(rotation_dir * angle * (distance / len), center_pt);
|
||||
}
|
||||
|
||||
distance -= len;
|
||||
}
|
||||
|
||||
if (distance < 0)
|
||||
return std::make_optional<Point>(point);
|
||||
return point;
|
||||
|
||||
prev_point = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Failed.
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<Point> sample_path_point_at_distance_from_end(const SmoothPath &path, double distance)
|
||||
{
|
||||
if (distance >= 0) {
|
||||
for (const SmoothPathElement& el : path) {
|
||||
auto it = el.path.begin();
|
||||
auto end = el.path.end();
|
||||
Point prev_point = it->point;
|
||||
for (++it; it != end; ++it) {
|
||||
Point point = it->point;
|
||||
if (it->linear()) {
|
||||
// Linear segment
|
||||
Vec2d v = (point - prev_point).cast<double>();
|
||||
double lsqr = v.squaredNorm();
|
||||
if (lsqr > sqr(distance))
|
||||
return std::make_optional<Point>(prev_point + (v * (distance / sqrt(lsqr))).cast<coord_t>());
|
||||
distance -= sqrt(lsqr);
|
||||
}
|
||||
else {
|
||||
// Circular segment
|
||||
float angle = Geometry::ArcWelder::arc_angle(prev_point.cast<float>(), point.cast<float>(), it->radius);
|
||||
double len = std::abs(it->radius) * angle;
|
||||
if (len > distance) {
|
||||
// Rotate the segment end point in reverse towards the start point.
|
||||
return std::make_optional<Point>(prev_point.rotated(-angle * (distance / len),
|
||||
Geometry::ArcWelder::arc_center(prev_point.cast<float>(), point.cast<float>(), it->radius, it->ccw()).cast<coord_t>()));
|
||||
}
|
||||
distance -= len;
|
||||
}
|
||||
if (distance < 0)
|
||||
return std::make_optional<Point>(point);
|
||||
prev_point = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Failed.
|
||||
return {};
|
||||
std::optional<Point> sample_path_point_at_distance_from_end(const SmoothPath &path, double distance) {
|
||||
SmoothPath path_reversed = path;
|
||||
reverse(path_reversed);
|
||||
return sample_path_point_at_distance_from_start(path_reversed, distance);
|
||||
}
|
||||
|
||||
// Clip length of a smooth path, for seam hiding.
|
||||
|
@ -211,7 +211,7 @@ std::optional<Point> wipe_hide_seam(const SmoothPath &path, bool is_hole, double
|
||||
// Wipe move cannot be calculated, the loop is not long enough. This should not happen due to the longer_than() test above.
|
||||
return {};
|
||||
}
|
||||
if (std::optional<Point> p = sample_path_point_at_distance_from_end(path, wipe_length); p)
|
||||
if (std::optional<Point> p = sample_path_point_at_distance_from_start(path, wipe_length); p)
|
||||
p_prev = *p;
|
||||
else
|
||||
// Wipe move cannot be calculated, the loop is not long enough. This should not happen due to the longer_than() test above.
|
||||
@ -231,7 +231,7 @@ std::optional<Point> wipe_hide_seam(const SmoothPath &path, bool is_hole, double
|
||||
}
|
||||
// Rotate the forward segment inside by 1/3 of the wedge angle.
|
||||
auto v_rotated = Eigen::Rotation2D(angle_inside) * (p_next - p_current).cast<double>().normalized();
|
||||
return std::make_optional<Point>(p_current + (v_rotated * wipe_length).cast<coord_t>());
|
||||
return p_current + (v_rotated * wipe_length).cast<coord_t>();
|
||||
}
|
||||
|
||||
return {};
|
||||
|
Loading…
x
Reference in New Issue
Block a user