mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 04:36:10 +08:00
Class to interpolate layer height distribution based on BSplines
This commit is contained in:
parent
c3f7a226a0
commit
97f4301398
@ -43,6 +43,8 @@ src/libslic3r/IO.hpp
|
||||
src/libslic3r/Layer.cpp
|
||||
src/libslic3r/Layer.hpp
|
||||
src/libslic3r/LayerRegion.cpp
|
||||
src/libslic3r/LayerHeightSpline.hpp
|
||||
src/libslic3r/LayerHeightSpline.cpp
|
||||
src/libslic3r/libslic3r.h
|
||||
src/libslic3r/Line.cpp
|
||||
src/libslic3r/Line.hpp
|
||||
@ -139,6 +141,7 @@ xsp/Geometry.xsp
|
||||
xsp/GUI.xsp
|
||||
xsp/GUI_3DScene.xsp
|
||||
xsp/Layer.xsp
|
||||
xsp/LayerHeightSpline.xsp
|
||||
xsp/Line.xsp
|
||||
xsp/Model.xsp
|
||||
xsp/MotionPlanner.xsp
|
||||
|
@ -228,6 +228,7 @@ for my $class (qw(
|
||||
Slic3r::Layer
|
||||
Slic3r::Layer::Region
|
||||
Slic3r::Layer::Support
|
||||
Slic3r::LayerHeightSpline
|
||||
Slic3r::Line
|
||||
Slic3r::Linef3
|
||||
Slic3r::Model
|
||||
|
194
xs/src/libslic3r/LayerHeightSpline.cpp
Normal file
194
xs/src/libslic3r/LayerHeightSpline.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* This class represents a set of layers and their heights.
|
||||
* It is intended for smoothing the height distribution (avoid very thin
|
||||
* layers next to thick layers) and to correctly interpolate higher layers if
|
||||
* a layer height changes somewhere in a lower position at the object.
|
||||
* Uses http://www.eol.ucar.edu/homes/granger/bspline/doc/ for spline computation.
|
||||
*/
|
||||
|
||||
#include "LayerHeightSpline.hpp"
|
||||
#include <cmath> // std::abs
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
LayerHeightSpline::LayerHeightSpline(coordf_t object_height)
|
||||
: _object_height(object_height), _layer_height_spline(NULL)
|
||||
{
|
||||
this->_is_valid = false;
|
||||
this->_update_required = true;
|
||||
}
|
||||
|
||||
LayerHeightSpline::~LayerHeightSpline()
|
||||
{
|
||||
if (this->_layer_height_spline) {
|
||||
delete this->_layer_height_spline;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicates whether the object has valid data and the spline was successfully computed or not.
|
||||
*/
|
||||
bool LayerHeightSpline::hasData()
|
||||
{
|
||||
return this->_is_valid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Does this object expect new layer heights during the slice step or should
|
||||
* we use the layer heights values provided by the spline?
|
||||
* An update is required if a config option is changed which affects the layer height.
|
||||
* An update is not required if the spline was modified by a user interaction.
|
||||
*/
|
||||
bool LayerHeightSpline::updateRequired()
|
||||
{
|
||||
bool result = true; // update spline by default
|
||||
if(!this->_update_required && this->_is_valid) {
|
||||
result = false;
|
||||
}
|
||||
this->_update_required = true; // reset to default after request
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't require an update for exactly one iteration.
|
||||
*/
|
||||
void LayerHeightSpline::suppressUpdate() {
|
||||
if (this->_is_valid) {
|
||||
this->_update_required = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set absolute layer positions in object coordinates.
|
||||
* Heights (thickness of each layer) is generated from this list.
|
||||
*/
|
||||
bool LayerHeightSpline::setLayers(std::vector<coordf_t> layers)
|
||||
{
|
||||
this->_original_layers = layers;
|
||||
|
||||
// generate updated layer height list from layers
|
||||
this->_internal_layer_heights.clear();
|
||||
coordf_t last_z = 0;
|
||||
for (std::vector<coordf_t>::const_iterator l = this->_original_layers.begin(); l != this->_original_layers.end(); ++l) {
|
||||
this->_internal_layer_heights.push_back(*l-last_z);
|
||||
last_z = *l;
|
||||
}
|
||||
|
||||
// add 0-values at both ends to achieve correct boundary conditions
|
||||
this->_internal_layers = this->_original_layers;
|
||||
this->_internal_layers.insert(this->_internal_layers.begin(), 0); // add z = 0 to the front
|
||||
this->_internal_layers.push_back(this->_internal_layers.back()+1); // and object_height + 1 to the end
|
||||
this->_internal_layer_heights.insert(this->_internal_layer_heights.begin(), 0);
|
||||
this->_internal_layer_heights.push_back(0);
|
||||
|
||||
return this->_updateBSpline();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update only the desired thickness of the layers, but not their positions!
|
||||
* This modifies the y-values for the spline computation and only affects
|
||||
* the resulting layers which can be obtained with getInterpolatedLayers.
|
||||
* The argument vector must be of the same size as the layers vector.
|
||||
*/
|
||||
bool LayerHeightSpline::updateLayerHeights(std::vector<coordf_t> heights)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// do we receive the correct number of values?
|
||||
if(heights.size() == this->_internal_layers.size()-2) {
|
||||
this->_internal_layer_heights = heights;
|
||||
// add leading an trailing 0-value
|
||||
this->_internal_layer_heights.insert(this->_internal_layer_heights.begin(), 0);
|
||||
this->_internal_layer_heights.push_back(0);
|
||||
result = this->_updateBSpline();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the this object, remove database and interpolated results.
|
||||
*/
|
||||
void LayerHeightSpline::clear()
|
||||
{
|
||||
this->_original_layers.clear();
|
||||
this->_internal_layers.clear();
|
||||
this->_internal_layer_heights.clear();
|
||||
delete this->_layer_height_spline;
|
||||
this->_layer_height_spline = NULL;
|
||||
this->_is_valid = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get a full set of layer z-positions by interpolation along the spline.
|
||||
*/
|
||||
std::vector<coordf_t> LayerHeightSpline::getInterpolatedLayers() const
|
||||
{
|
||||
std::vector<coordf_t> layers;
|
||||
if(this->_is_valid) {
|
||||
// preserve first layer for bed contact
|
||||
layers.push_back(this->_original_layers[0]);
|
||||
coordf_t z = this->_original_layers[0];
|
||||
coordf_t h;
|
||||
coordf_t h_diff = 0;
|
||||
coordf_t eps = 0.0001;
|
||||
while(z <= this->_object_height) {
|
||||
h = 0;
|
||||
// find intersection between layer height and spline
|
||||
do {
|
||||
h += h_diff/2;
|
||||
h = this->_layer_height_spline->evaluate(z+h);
|
||||
h_diff = this->_layer_height_spline->evaluate(z+h) - h;
|
||||
} while(std::abs(h_diff) > eps);
|
||||
z += h;
|
||||
layers.push_back(z);
|
||||
}
|
||||
// how to make sure, the last layer is not higher than object while maintaining between min/max layer height?
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate interpolated layer height (thickness) at given z-position
|
||||
*/
|
||||
const coordf_t LayerHeightSpline::getLayerHeightAt(coordf_t height)
|
||||
{
|
||||
coordf_t result = 0;
|
||||
if (this->_is_valid) {
|
||||
result = this->_layer_height_spline->evaluate(height);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal method to re-compute the spline
|
||||
*/
|
||||
bool LayerHeightSpline::_updateBSpline()
|
||||
{
|
||||
bool result = false;
|
||||
//TODO: exception if not enough points?
|
||||
|
||||
delete this->_layer_height_spline;
|
||||
this->_layer_height_spline = new BSpline<double>(&this->_internal_layers[0],
|
||||
this->_internal_layers.size(),
|
||||
&this->_internal_layer_heights[0],
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (this->_layer_height_spline->ok()) {
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
std::cerr << "Spline setup failed." << std::endl;
|
||||
}
|
||||
|
||||
this->_is_valid = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
40
xs/src/libslic3r/LayerHeightSpline.hpp
Normal file
40
xs/src/libslic3r/LayerHeightSpline.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef slic3r_LayerHeightSpline_hpp_
|
||||
#define slic3r_LayerHeightSpline_hpp_
|
||||
|
||||
#include "libslic3r.h"
|
||||
#include "BSpline/BSpline.h" // Warning: original BSplineBase.h/cpp merged into BSpline.h/cpp to avoid dependency issues caused by Build::WithXSpp which tries to compile all .cpp files in /src
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
class LayerHeightSpline
|
||||
{
|
||||
public:
|
||||
LayerHeightSpline(coordf_t object_height);
|
||||
~LayerHeightSpline();
|
||||
bool hasData(); // indicate that we have valid data
|
||||
bool updateRequired(); // indicate whether we want to generate a new spline from the layers
|
||||
void suppressUpdate();
|
||||
bool setLayers(std::vector<coordf_t> layers);
|
||||
bool updateLayerHeights(std::vector<coordf_t> heights);
|
||||
void clear();
|
||||
std::vector<coordf_t> getOriginalLayers() const { return this->_original_layers; };
|
||||
std::vector<coordf_t> getInterpolatedLayers() const;
|
||||
const coordf_t getLayerHeightAt(coordf_t height);
|
||||
|
||||
private:
|
||||
bool _updateBSpline();
|
||||
|
||||
coordf_t _object_height;
|
||||
bool _is_valid;
|
||||
bool _update_required; // this should be always true except if we want to generate new layers from this spline
|
||||
std::vector<coordf_t> _original_layers;
|
||||
std::vector<coordf_t> _internal_layers;
|
||||
std::vector<coordf_t> _internal_layer_heights;
|
||||
BSpline<double> *_layer_height_spline;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@ REGISTER_CLASS(GCodeWriter, "GCode::Writer");
|
||||
REGISTER_CLASS(Layer, "Layer");
|
||||
REGISTER_CLASS(SupportLayer, "Layer::Support");
|
||||
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
||||
REGISTER_CLASS(LayerHeightSpline, "LayerHeightSpline");
|
||||
REGISTER_CLASS(Line, "Line");
|
||||
REGISTER_CLASS(Linef3, "Linef3");
|
||||
REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator");
|
||||
|
23
xs/xsp/LayerHeightSpline.xsp
Normal file
23
xs/xsp/LayerHeightSpline.xsp
Normal file
@ -0,0 +1,23 @@
|
||||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/LayerHeightSpline.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::LayerHeightSpline} class LayerHeightSpline {
|
||||
// owned by PrintObject, no constructor/destructor
|
||||
|
||||
bool hasData();
|
||||
bool updateRequired();
|
||||
void suppressUpdate();
|
||||
bool setLayers(std::vector<double> layers)
|
||||
%code%{ RETVAL = THIS->setLayers(layers); %};
|
||||
bool updateLayerHeights(std::vector<double> heights)
|
||||
%code%{ RETVAL = THIS->updateLayerHeights(heights); %};
|
||||
void clear();
|
||||
std::vector<double> getOriginalLayers();
|
||||
std::vector<double> getInterpolatedLayers();
|
||||
coordf_t getLayerHeightAt(coordf_t height);
|
||||
//%code%{ RETVAL = THIS->upper_layer; %};
|
||||
};
|
@ -169,6 +169,9 @@ Ref<Layer> O_OBJECT_SLIC3R_T
|
||||
SupportLayer* O_OBJECT_SLIC3R
|
||||
Ref<SupportLayer> O_OBJECT_SLIC3R_T
|
||||
|
||||
LayerHeightSpline* O_OBJECT_SLIC3R
|
||||
Ref<LayerHeightSpline> O_OBJECT_SLIC3R_T
|
||||
|
||||
PlaceholderParser* O_OBJECT_SLIC3R
|
||||
Ref<PlaceholderParser> O_OBJECT_SLIC3R_T
|
||||
Clone<PlaceholderParser> O_OBJECT_SLIC3R_T
|
||||
|
@ -129,6 +129,9 @@
|
||||
%typemap{Layer*};
|
||||
%typemap{Ref<Layer>}{simple};
|
||||
|
||||
%typemap{LayerHeightSpline*};
|
||||
%typemap{Ref<LayerHeightSpline>}{simple};
|
||||
|
||||
%typemap{SupportLayer*};
|
||||
%typemap{Ref<SupportLayer>}{simple};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user