550 {
551 size_t speed_sections_count = std::min(
overlaps.values.size(), speeds.values.size());
552 std::vector<std::pair<float, float>> speed_sections;
553
554
555
556 for (size_t i = 0; i < speed_sections_count; i++) {
558 float speed = speeds.get_at(i).percent ? (ext_perimeter_speed * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value;
559 speed_sections.push_back({
distance, speed});
560 }
561 std::sort(speed_sections.begin(), speed_sections.end(),
562 [](const std::pair<float, float> &a, const std::pair<float, float> &b) {
563 if (a.first == b.first) {
564 return a.second > b.second;
565 }
566 return a.first < b.first; });
567
568 std::pair<float, float> last_section{INFINITY, 0};
569 for (auto §ion : speed_sections) {
570 if (section.first == last_section.first) {
571 section.second = last_section.second;
572 } else {
573 last_section = section;
574 }
575 }
576
577
578 float smallest_distance_with_lower_speed = std::numeric_limits<float>::infinity();
579 bool found = false;
580 for (const auto& section : speed_sections) {
581 if (section.second <= original_speed) {
582 if (section.first < smallest_distance_with_lower_speed) {
583 smallest_distance_with_lower_speed = section.first;
584 found = true;
585 }
586 }
587 }
588
589
590
591 if (!found)
592 smallest_distance_with_lower_speed=-1.f;
593
594
595 auto calculate_speed = [&speed_sections, &original_speed](
float distance) {
596 float final_speed;
597 if (distance <= speed_sections.front().first) {
598 final_speed = original_speed;
599 } else if (distance >= speed_sections.back().first) {
600 final_speed = speed_sections.back().second;
601 } else {
602 size_t section_idx = 0;
603 while (distance > speed_sections[section_idx + 1].first) {
604 section_idx++;
605 }
606 float t = (
distance - speed_sections[section_idx].first) /
607 (speed_sections[section_idx + 1].first - speed_sections[section_idx].first);
608 t = std::clamp(t, 0.0f, 1.0f);
609 final_speed = (1.0f - t) * speed_sections[section_idx].second + t * speed_sections[section_idx + 1].second;
610 }
611 return round(final_speed);
612 };
613
614
615
616
617
618 auto effective_speed = [&calculate_speed, original_speed](
float distance) {
619 return std::min(calculate_speed(distance), original_speed);
620 };
621
622
623 const std::unordered_map<Point3, double, Point3Hash> *known = nullptr;
626 known = &precomputed->distances;
629 auto known_distance = [known](const Point3 &point) -> const double * {
630 if (known == nullptr)
631 return nullptr;
632 auto it = known->find(point);
633 return it == known->end() ? nullptr : &it->second;
634 };
635
636 std::vector<ExtendedPoint<3>> extended_points =
638 smallest_distance_with_lower_speed, effective_speed, fan_overlap_threshold,
639 known_distance);
640 const auto width_inv = 1.0f / path.width;
641 std::vector<ProcessedPoint> processed_points;
642 processed_points.reserve(extended_points.size());
643 for (size_t i = 0; i < extended_points.size(); i++) {
644 const ExtendedPoint<3>& curr = extended_points[i];
645 const ExtendedPoint<3>& next = extended_points[i + 1 < extended_points.size() ? i + 1 : i];
646
647 float artificial_distance_to_curled_lines = 0.0;
648 if(slowdown_for_curled_edges) {
649
650 const double dist_limit = 10.0 * path.width;
651 {
652 Vec3d middle = 0.5 * (curr.position + next.position);
653 auto line_indices = prev_curled.all_lines_in_radius(
Point::new_scale(middle),
655 if (!line_indices.empty()) {
656 double len = (next.position - curr.position).norm();
657
658
659
660
661 if (len > 2) {
662 Vec2d dir =
Vec2d(next.position.head<2>() - curr.position.head<2>()) / len;
664
666 scaled(
Vec2d(curr.position.head<2>() + right * dist_limit)),
667 scaled(
Vec2d(next.position.head<2>() + right * dist_limit)),
668 scaled(
Vec2d(next.position.head<2>() - right * dist_limit)),
669 scaled(
Vec2d(curr.position.head<2>() - right * dist_limit)),
670 };
671
672 double projected_lengths_sum = 0;
673 for (size_t idx : line_indices) {
674 const CurledLine& line = prev_curled.get_line(idx);
677 continue;
679 projected_lengths_sum += projected_length;
680 }
681 if (projected_lengths_sum < 0.4 * len) {
682 line_indices.clear();
683 }
684 }
685
686 for (size_t idx : line_indices) {
687 const CurledLine &line = prev_curled.get_line(idx);
689 float dist = path.width * (1.0 - (distance_from_curled / dist_limit)) *
690 (1.0 - (distance_from_curled / dist_limit)) *
691 (line.curled_height / (path.height * 10.0f));
692 artificial_distance_to_curled_lines = std::max(artificial_distance_to_curled_lines,
dist);
693 }
694 }
695 }
696 }
697
698 float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
699
700
701 extrusion_speed = std::min(extrusion_speed, original_speed);
702
703 if(slowdown_for_curled_edges) {
704 float curled_speed = calculate_speed(artificial_distance_to_curled_lines);
705 extrusion_speed = std::min(curled_speed, extrusion_speed);
706 }
707
708 float overlap = std::min(1 - (curr.distance+artificial_distance_to_curled_lines) * width_inv, 1 - (next.distance+artificial_distance_to_curled_lines) * width_inv);
709
710 processed_points.push_back({Point3(
scaled(curr.position)), extrusion_speed, overlap});
711 }
712 return processed_points;
713 }
AABBTreeLines::LinesDistancer< Linef3 > Boundaries
Definition ExtrusionProcessor.hpp:492
std::unordered_map< const PrintObject *, std::shared_ptr< const Boundaries > > prev_layer_boundaries
Definition ExtrusionProcessor.hpp:494
const PrecomputedOverhangLayer * precomputed_for(const PrintObject *object) const
Definition ExtrusionProcessor.hpp:502
AABBTreeLines::LinesDistancer< CurledLine > CurledLines
Definition ExtrusionProcessor.hpp:493
static const T & or_empty(const std::shared_ptr< const T > &tree)
Definition ExtrusionProcessor.hpp:509
std::unordered_map< const PrintObject *, const Layer * > prev_layer_sources
Definition ExtrusionProcessor.hpp:497
const PrintObject * current_object
Definition ExtrusionProcessor.hpp:500
std::unordered_map< const PrintObject *, std::shared_ptr< const CurledLines > > prev_curled_extrusions
Definition ExtrusionProcessor.hpp:495
Layer * lower_layer
Definition Layer.hpp:147
static Point new_scale(coordf_t x, coordf_t y)
Definition Point.hpp:214
#define scale_(val)
Definition libslic3r.h:106
bool inside(const Polygons &polygons, const Point &p)
Definition TreeNode.cpp:160
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:298
float distance(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:19
double distance_to(const L &line, const Vec< Dim< L >, Scalar< L > > &point)
Definition Line.hpp:83
const Layer * layer
Definition ExtrusionProcessor.hpp:450
std::vector< Line > Lines
Definition Line.hpp:20
Slic3r::Lines intersection_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip)
Definition ClipperUtils.hpp:571
BoundingBox scaled(const BoundingBoxf &bb)
Definition BoundingBox.hpp:284
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
std::vector< ExtendedPoint< L::Dim > > estimate_points_properties(const POINTS &input_points, const AABBTreeLines::LinesDistancer< L > &unscaled_prev_layer, float flow_width, float max_line_length=-1.0f, float min_distance=-1.0f, const std::function< float(float)> &distance_to_speed={}, float fan_overlap_threshold=-1.0f, const KNOWN_DISTANCES &known_distance=KNOWN_DISTANCES{})
Definition ExtrusionProcessor.hpp:52
constexpr Eigen::Matrix< Tout, 2, EigenArgs... > unscaled(const Slic3r::Point &v) noexcept
Definition Arrange.cpp:81
bool overlaps(const ExPolygons &expolys1, const ExPolygons &expolys2)
Definition ExPolygon.cpp:192
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
Slic3r::Polygon Polygon
Definition Emboss.cpp:101
@ right
Definition MarchingSquares.hpp:190