484{
486 if (!line.modified) {
488 return;
489 }
490
491
492
493 const char *comment = line.raw.data();
494 while (*comment != ';' && *comment != 0) ++comment;
495 if (*comment != ';')
496 comment = nullptr;
497
498
499 float l = line.dist_xyz();
500
502
503
504
505
506 int delta_volumetric_rate = std::round(std::max({
507 fabs(line.volumetric_extrusion_rate_end - line.volumetric_extrusion_rate_start),
508
509 fabs(line.volumetric_extrusion_rate - line.volumetric_extrusion_rate_start),
510 fabs(line.volumetric_extrusion_rate - line.volumetric_extrusion_rate_end),
511 }));
512
513
514
515
516
517
518 constexpr int NON_TRIVIAL_RATE_DELTA = 10;
519 if (nSegments == 1 || delta_volumetric_rate < NON_TRIVIAL_RATE_DELTA) {
520 push_line_to_output(line_idx, line.feedrate() * line.volumetric_correction_avg(), comment);
521 } else
522 {
523 const float original_feedrate = line.feedrate();
524
525 line.pos_start[4] = line.volumetric_extrusion_rate_start * line.pos_end[4] / line.volumetric_extrusion_rate;
526 line.pos_end [4] = line.volumetric_extrusion_rate_end * line.pos_end[4] / line.volumetric_extrusion_rate;
527
528
529
530 if (line.volumetric_extrusion_rate > line.volumetric_extrusion_rate_start &&
531 line.volumetric_extrusion_rate > line.volumetric_extrusion_rate_end) {
532
533 const double original_extrusion = (double) l * line.volumetric_extrusion_rate / original_feedrate;
534
535
537 const double max_sloped_extrusion = original_extrusion - min_steady_extrusion;
538 assert(max_sloped_extrusion > 0);
539
540
541
542
543 const auto pow2 = [](const double x) { return x * x; };
544 const double e_2 = pow2(line.volumetric_extrusion_rate);
545 const double e0_2 = pow2(line.volumetric_extrusion_rate_start);
546 const double e1_2 = pow2(line.volumetric_extrusion_rate_end);
547 const double sp = line.max_volumetric_extrusion_rate_slope_positive;
548 const double sn = line.max_volumetric_extrusion_rate_slope_negative;
549 const double sloped_extrusion = (e_2 - e0_2) / 2 / sp + (e_2 - e1_2) / 2 / sn;
550
551 double target_max_extrusion_rate = line.volumetric_extrusion_rate;
552 if (sloped_extrusion > max_sloped_extrusion) {
553
554
555 target_max_extrusion_rate = std::sqrt((2 * max_sloped_extrusion * sp * sn + sn * e0_2 + sp * e1_2) / (sp + sn));
556
557
558
559 if (target_max_extrusion_rate <= line.volumetric_extrusion_rate_start ||
560 target_max_extrusion_rate <= line.volumetric_extrusion_rate_end) {
561 goto single_slope_fallback;
562 }
563 }
564 assert(target_max_extrusion_rate > line.volumetric_extrusion_rate_start);
565 assert(target_max_extrusion_rate > line.volumetric_extrusion_rate_end);
566 assert(target_max_extrusion_rate <= line.volumetric_extrusion_rate);
567
568
569 delta_volumetric_rate = std::round(std::min({
570 fabs(target_max_extrusion_rate - line.volumetric_extrusion_rate_start),
571 fabs(target_max_extrusion_rate - line.volumetric_extrusion_rate_end),
572 }));
573
574 if (delta_volumetric_rate >= NON_TRIVIAL_RATE_DELTA) {
575
576 const double target_max_feedrate = original_feedrate * target_max_extrusion_rate / line.volumetric_extrusion_rate;
577 assert(target_max_feedrate <= original_feedrate);
578
579
580 const double t_acc = (target_max_extrusion_rate - line.volumetric_extrusion_rate_start) / sp;
581 const double l_acc = t_acc * (target_max_feedrate + line.pos_start[4]) / 2;
582 const double t_dec = (target_max_extrusion_rate - line.volumetric_extrusion_rate_end) / sn;
583 const double l_dec = t_dec * (target_max_feedrate + line.pos_end[4]) / 2;
584
585 float pos_end_bak[5];
586 memcpy(pos_end_bak, line.pos_end, sizeof(float) * 5);
587 float pos_start[5];
588 float pos_end[5];
589 memcpy(pos_start, line.pos_start, sizeof(float) * 5);
590 memcpy(pos_end, line.pos_end, sizeof(float) * 5);
591
592
593 float t = l_acc / l;
594 for (int i = 0; i < 4; ++i) {
595 pos_end[i] = pos_start[i] + (pos_end_bak[i] - pos_start[i]) * t;
596 line.pos_provided[i] = true;
597 }
598
600 assert(nSegments > 0);
601 for (size_t i = 1; i <= nSegments; ++i) {
602 t = float(i) / float(nSegments);
603 for (size_t j = 0; j < 4; ++j) {
604 line.pos_end[j] = pos_start[j] + (pos_end[j] - pos_start[j]) * t;
605 line.pos_provided[j] = true;
606 }
607
608 push_line_to_output(line_idx, pos_start[4] + (target_max_feedrate - pos_start[4]) * (
float(i) - 0.5f) /
float(nSegments), comment);
609 comment = nullptr;
610 memcpy(line.pos_start, line.pos_end, sizeof(float)*5);
611 }
612
613
614 t = (l - l_dec) / l;
615 for (int i = 0; i < 4; ++i) {
616 line.pos_end[i] = pos_start[i] + (pos_end_bak[i] - pos_start[i]) * t;
617 }
618
620 memcpy(line.pos_start, line.pos_end, sizeof(float) * 5);
621
622
623 memcpy(pos_start, line.pos_end, sizeof(float) * 5);
624 line.pos_start[4] = target_max_feedrate;
625 pos_start[4] = target_max_feedrate;
626
628 assert(nSegments > 0);
629 for (size_t i = 1; i <= nSegments; ++ i) {
630 t = float(i) / float(nSegments);
631 for (size_t j = 0; j < 4; ++ j) {
632 line.pos_end[j] = pos_start[j] + (pos_end_bak[j] - pos_start[j]) * t;
633 }
634
635 push_line_to_output(line_idx, pos_start[4] + (pos_end_bak[4] - pos_start[4]) * (
float(i) - 0.5f) /
float(nSegments),
nullptr);
636 memcpy(line.pos_start, line.pos_end, sizeof(float)*5);
637 }
638
639
640 for (int i = 0; i < 4; ++i) {
641 line.pos_end[i] = pos_end_bak[i];
642 }
644
645 return;
646 }
647 }
648single_slope_fallback:
649 bool accelerating = line.volumetric_extrusion_rate_start < line.volumetric_extrusion_rate_end;
650 float feed_avg = 0.5f * (line.pos_start[4] + line.pos_end[4]);
651
653 line.max_volumetric_extrusion_rate_slope_negative;
654
655
656 float t_total = line.dist_xyz() / feed_avg;
657
658
660 float l_acc = l;
661 float l_steady = 0.f;
662 if (t_acc < t_total) {
663
664 l_acc = t_acc * feed_avg;
665 l_steady = l - l_acc;
667 l_acc = l;
668 l_steady = 0.f;
669 } else
671 }
672 float pos_start[5];
673 float pos_end[5];
674 float pos_end2[4];
675 memcpy(pos_start, line.pos_start, sizeof(float) * 5);
676 memcpy(pos_end, line.pos_end, sizeof(float) * 5);
677 if (l_steady > 0.f) {
678
679 if (accelerating) {
680
681 memcpy(pos_end2, pos_end, sizeof(float)*4);
682 float t = l_acc / l;
683 for (int i = 0; i < 4; ++ i) {
684 pos_end[i] = pos_start[i] + (pos_end[i] - pos_start[i]) * t;
685 line.pos_provided[i] = true;
686 }
687 } else {
688
689 float t = l_steady / l;
690 for (int i = 0; i < 4; ++ i) {
691 line.pos_end[i] = pos_start[i] + (pos_end[i] - pos_start[i]) * t;
692 line.pos_provided[i] = true;
693 }
695 comment = nullptr;
696
697 float new_pos_start_feedrate = pos_start[4];
698
699 memcpy(line.pos_start, line.pos_end, sizeof(float)*5);
700 memcpy(pos_start, line.pos_end, sizeof(float)*5);
701
702 line.pos_start[4] = new_pos_start_feedrate;
703 pos_start[4] = new_pos_start_feedrate;
704 }
705 }
706
707 for (size_t i = 1; i < nSegments; ++ i) {
708 float t = float(i) / float(nSegments);
709 for (size_t j = 0; j < 4; ++ j) {
710 line.pos_end[j] = pos_start[j] + (pos_end[j] - pos_start[j]) * t;
711 line.pos_provided[j] = true;
712 }
713
714 push_line_to_output(line_idx, pos_start[4] + (pos_end[4] - pos_start[4]) * (
float(i) - 0.5f) /
float(nSegments), comment);
715 comment = nullptr;
716 memcpy(line.pos_start, line.pos_end, sizeof(float)*5);
717 }
718 if (l_steady > 0.f && accelerating) {
719 for (int i = 0; i < 4; ++ i) {
720 line.pos_end[i] = pos_end2[i];
721 line.pos_provided[i] = true;
722 }
724 } else {
725 for (int i = 0; i < 4; ++ i) {
726 line.pos_end[i] = pos_end[i];
727 line.pos_provided[i] = true;
728 }
730 }
731 }
732}
void push_line_to_output(size_t line_idx, float new_feedrate, const char *comment)
Definition PressureEqualizer.cpp:930
void push_to_output(GCodeG1Formatter &formatter)
Definition PressureEqualizer.cpp:868
zaa_minimize_perimeter_height max_volumetric_extrusion_rate_slope((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_segment_length))((ConfigOptionBool