mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-13 23:45:52 +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.cpp
|
||||||
src/libslic3r/Layer.hpp
|
src/libslic3r/Layer.hpp
|
||||||
src/libslic3r/LayerRegion.cpp
|
src/libslic3r/LayerRegion.cpp
|
||||||
|
src/libslic3r/LayerHeightSpline.hpp
|
||||||
|
src/libslic3r/LayerHeightSpline.cpp
|
||||||
src/libslic3r/libslic3r.h
|
src/libslic3r/libslic3r.h
|
||||||
src/libslic3r/Line.cpp
|
src/libslic3r/Line.cpp
|
||||||
src/libslic3r/Line.hpp
|
src/libslic3r/Line.hpp
|
||||||
@ -139,6 +141,7 @@ xsp/Geometry.xsp
|
|||||||
xsp/GUI.xsp
|
xsp/GUI.xsp
|
||||||
xsp/GUI_3DScene.xsp
|
xsp/GUI_3DScene.xsp
|
||||||
xsp/Layer.xsp
|
xsp/Layer.xsp
|
||||||
|
xsp/LayerHeightSpline.xsp
|
||||||
xsp/Line.xsp
|
xsp/Line.xsp
|
||||||
xsp/Model.xsp
|
xsp/Model.xsp
|
||||||
xsp/MotionPlanner.xsp
|
xsp/MotionPlanner.xsp
|
||||||
|
@ -228,6 +228,7 @@ for my $class (qw(
|
|||||||
Slic3r::Layer
|
Slic3r::Layer
|
||||||
Slic3r::Layer::Region
|
Slic3r::Layer::Region
|
||||||
Slic3r::Layer::Support
|
Slic3r::Layer::Support
|
||||||
|
Slic3r::LayerHeightSpline
|
||||||
Slic3r::Line
|
Slic3r::Line
|
||||||
Slic3r::Linef3
|
Slic3r::Linef3
|
||||||
Slic3r::Model
|
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(Layer, "Layer");
|
||||||
REGISTER_CLASS(SupportLayer, "Layer::Support");
|
REGISTER_CLASS(SupportLayer, "Layer::Support");
|
||||||
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
||||||
|
REGISTER_CLASS(LayerHeightSpline, "LayerHeightSpline");
|
||||||
REGISTER_CLASS(Line, "Line");
|
REGISTER_CLASS(Line, "Line");
|
||||||
REGISTER_CLASS(Linef3, "Linef3");
|
REGISTER_CLASS(Linef3, "Linef3");
|
||||||
REGISTER_CLASS(PerimeterGenerator, "Layer::PerimeterGenerator");
|
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
|
SupportLayer* O_OBJECT_SLIC3R
|
||||||
Ref<SupportLayer> O_OBJECT_SLIC3R_T
|
Ref<SupportLayer> O_OBJECT_SLIC3R_T
|
||||||
|
|
||||||
|
LayerHeightSpline* O_OBJECT_SLIC3R
|
||||||
|
Ref<LayerHeightSpline> O_OBJECT_SLIC3R_T
|
||||||
|
|
||||||
PlaceholderParser* O_OBJECT_SLIC3R
|
PlaceholderParser* O_OBJECT_SLIC3R
|
||||||
Ref<PlaceholderParser> O_OBJECT_SLIC3R_T
|
Ref<PlaceholderParser> O_OBJECT_SLIC3R_T
|
||||||
Clone<PlaceholderParser> O_OBJECT_SLIC3R_T
|
Clone<PlaceholderParser> O_OBJECT_SLIC3R_T
|
||||||
|
@ -129,6 +129,9 @@
|
|||||||
%typemap{Layer*};
|
%typemap{Layer*};
|
||||||
%typemap{Ref<Layer>}{simple};
|
%typemap{Ref<Layer>}{simple};
|
||||||
|
|
||||||
|
%typemap{LayerHeightSpline*};
|
||||||
|
%typemap{Ref<LayerHeightSpline>}{simple};
|
||||||
|
|
||||||
%typemap{SupportLayer*};
|
%typemap{SupportLayer*};
|
||||||
%typemap{Ref<SupportLayer>}{simple};
|
%typemap{Ref<SupportLayer>}{simple};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user