OrcaSlicer/src/libslic3r/GCode/PchipInterpolatorHelper.cpp
Ioannis Giannakas 529c44d8e3
Enhancement: Adaptive Pressure advance (#5609)
* Adaptive Pressure advance options setup

* Dynamic PA - PCHIP interpolator code and tests

* Integrate dynamic PA with slicing code - emit new PA values per speed change

* Link adaptive PA to role change instead of speed change

* Adaptive PA - Alpha 2

Reduce the frequency of requested PA changes by introducing a "state" variable.
Implement user toggle for adapting PA for external walls for overhangs

* Hide adaptive PA for overhangs

* Convert Adaptive PA to use volumetric flow model and start preparing for converting to Gcode post processor

* Converted Dynamic PA to a post processing filter. Reverted changes in GCode cpp and created tagging mechanism to allow filter to apply PA changes.

* Removed adaptive PA for overhangs

* Foundations for two dimensional adaptive PA based on acceleration and volumetric flow speed

* Minor code cleanup and updating of tooltips

* Renaming files for better clarity and generate classes documentation

* Update src/libslic3r/PrintConfig.cpp

Co-authored-by: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com>

* Update src/libslic3r/PrintConfig.cpp

Co-authored-by: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com>

* Update src/libslic3r/PrintConfig.cpp

Co-authored-by: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com>

* Introduce average mm3_mm over the length of a multipath for adaptive PA

* Updates for multipath handling part 2

* Introduce average mm3_mm over the length of a multipath for adaptive PA

* Trigger PA evaluation more frequently to catch edge cases where speed changes across islands of the same feature type.

* Updates for multipath handling part 2

* Adaptive PA: Implement average flow estimation on loops

* Code formatting

* Fix adaptive PA not adapting for small disconnected external wall line segments.

* Updated to take max print speed of upcoming feature to calculate new PA value.

This is to resolve issue of incorrect PA value used when starting a new feature at an overhang.

* Code clean up

* Performance tuning

* Further performance tuning by reducing use of regex commands in the nested loops and fix bug preventing gcode line output

* Further performance tuning and tweaks to stop searching for max speed after the first travel move.

* Reduce debug information

* Updated debug info

* Fix an issue on seams on specific models when wipe before external perimeter was enabled. Also cleanup documentation and add new to-do's

* Prepare for adaptive PA for overhangs, fix wipe bug & clean up code and comments

* Initial commit for adapting PA when extruding fully overhanging perimeters

* Ignore wipe command when identifying current print speed

* Option to evaluate adaptive PA on overhang regions in preparation for Klipper experimental option testing

* Update to issue PA changes for varying flow conditions within the same feature

* Fix bug where adaptive PA was enabled erroneously for role changes and ignoring user's preference.

* Refactored some code

* More refactoring

* Some bug fixes and enabled comments only when verbose g-code is enabled

* Introduced dedicated PA option for bridges

* Code refactoring to optimise initialisation of PA processor (making it faster). Fix a bug where PA was not always set after a toolchange. Improve general error handling and robustness.

* Updates to adaptive PA tooltips

* Bridging PA check with Epsilon instead of 0.

* Adaptive PA: addressing comments

---------

Co-authored-by: ElectricalBoy <15651807+ElectricalBoy@users.noreply.github.com>
2024-07-28 22:52:08 +08:00

100 lines
2.7 KiB
C++

// PchipInterpolatorHelper.cpp
// OrcaSlicer
//
// Implementation file for the PchipInterpolatorHelper class
#include "PchipInterpolatorHelper.hpp"
#include <stdexcept>
#include <cmath>
#include <algorithm>
/**
* @brief Constructs the PCHIP interpolator with given data points.
* @param x The x-coordinates of the data points.
* @param y The y-coordinates of the data points.
*/
PchipInterpolatorHelper::PchipInterpolatorHelper(const std::vector<double>& x, const std::vector<double>& y) {
setData(x, y);
}
/**
* @brief Sets the data points for the interpolator.
* @param x The x-coordinates of the data points.
* @param y The y-coordinates of the data points.
* @throw std::invalid_argument if x and y have different sizes or if they contain fewer than two points.
*/
void PchipInterpolatorHelper::setData(const std::vector<double>& x, const std::vector<double>& y) {
if (x.size() != y.size() || x.size() < 2) {
throw std::invalid_argument("Input vectors must have the same size and contain at least two points.");
}
x_ = x;
y_ = y;
sortData();
computePCHIP();
}
/**
* @brief Sorts the data points by x-coordinate.
*/
void PchipInterpolatorHelper::sortData() {
std::vector<std::pair<double, double>> data;
for (size_t i = 0; i < x_.size(); ++i) {
data.emplace_back(x_[i], y_[i]);
}
std::sort(data.begin(), data.end());
for (size_t i = 0; i < data.size(); ++i) {
x_[i] = data[i].first;
y_[i] = data[i].second;
}
}
/**
* @brief Computes the PCHIP coefficients.
*/
void PchipInterpolatorHelper::computePCHIP() {
size_t n = x_.size() - 1;
h_.resize(n);
delta_.resize(n);
d_.resize(n+1);
for (size_t i = 0; i < n; ++i) {
h_[i] = h(i);
delta_[i] = delta(i);
}
d_[0] = delta_[0];
d_[n] = delta_[n-1];
for (size_t i = 1; i < n; ++i) {
if (delta_[i-1] * delta_[i] > 0) {
double w1 = 2 * h_[i] + h_[i-1];
double w2 = h_[i] + 2 * h_[i-1];
d_[i] = (w1 + w2) / (w1 / delta_[i-1] + w2 / delta_[i]);
} else {
d_[i] = 0;
}
}
}
/**
* @brief Interpolates the value at a given point.
*/
double PchipInterpolatorHelper::interpolate(double xi) const {
if (xi <= x_.front()) return y_.front();
if (xi >= x_.back()) return y_.back();
auto it = std::lower_bound(x_.begin(), x_.end(), xi);
size_t i = std::distance(x_.begin(), it) - 1;
double h_i = h_[i];
double t = (xi - x_[i]) / h_i;
double t2 = t * t;
double t3 = t2 * t;
double h00 = 2 * t3 - 3 * t2 + 1;
double h10 = t3 - 2 * t2 + t;
double h01 = -2 * t3 + 3 * t2;
double h11 = t3 - t2;
return h00 * y_[i] + h10 * h_i * d_[i] + h01 * y_[i+1] + h11 * h_i * d_[i+1];
}