一、切片
1、SlicingParameters 切片参数
cpp
struct SlicingParameters
{
SlicingParameters() = default;
static SlicingParameters create_from_config(
const PrintConfig &print_config,
const PrintObjectConfig &object_config,
coordf_t object_height,
const std::vector<unsigned int> &object_extruders);
// Has any raft layers?
bool has_raft() const { return raft_layers() > 0; }
size_t raft_layers() const { return base_raft_layers + interface_raft_layers; }
// Is the 1st object layer height fixed, or could it be varied?
bool first_object_layer_height_fixed() const { return ! has_raft() || first_object_layer_bridging; }
// Height of the object to be printed. This value does not contain the raft height.
coordf_t object_print_z_height() const { return object_print_z_max - object_print_z_min; }
bool valid { false };
// Number of raft layers.
size_t base_raft_layers { 0 };
// Number of interface layers including the contact layer.
size_t interface_raft_layers { 0 };
// Layer heights of the raft (base, interface and a contact layer).
coordf_t base_raft_layer_height { 0 };
coordf_t interface_raft_layer_height { 0 };
coordf_t contact_raft_layer_height { 0 };
// The regular layer height, applied for all but the first layer, if not overridden by layer ranges
// or by the variable layer thickness table.
coordf_t layer_height { 0 };
// Minimum / maximum layer height, to be used for the automatic adaptive layer height algorithm,
// or by an interactive layer height editor.
coordf_t min_layer_height { 0 };
coordf_t max_layer_height { 0 };
coordf_t max_suport_layer_height { 0 };
// First layer height of the print, this may be used for the first layer of the raft
// or for the first layer of the print.
coordf_t first_print_layer_height { 0 };
// Thickness of the first layer. This is either the first print layer thickness if printed without a raft,
// or a bridging flow thickness if printed over a non-soluble raft,
// or a normal layer height if printed over a soluble raft.
coordf_t first_object_layer_height { 0 };
// If the object is printed over a non-soluble raft, the first layer may be printed with a briding flow.
bool first_object_layer_bridging { false };
// Soluble interface? (PLA soluble in water, HIPS soluble in lemonen)
// otherwise the interface must be broken off.
bool soluble_interface { false };
// Gap when placing object over raft.
coordf_t gap_raft_object { 0 };
// Gap when placing support over object.
coordf_t gap_object_support { 0 };
// Gap when placing object over support.
coordf_t gap_support_object { 0 };
// Bottom and top of the printed object.
// If printed without a raft, object_print_z_min = 0 and object_print_z_max = object height.
// Otherwise object_print_z_min is equal to the raft height.
coordf_t raft_base_top_z { 0 };
coordf_t raft_interface_top_z { 0 };
coordf_t raft_contact_top_z { 0 };
// In case of a soluble interface, object_print_z_min == raft_contact_top_z, otherwise there is a gap between the raft and the 1st object layer.
coordf_t object_print_z_min { 0 };
coordf_t object_print_z_max { 0 };
};
object_print_z_max 为模型高度,在添加模型或导入模型时,会调用PrintObject::update_slicing_parameters()函数,通过SlicingParameters::create_from_config进行赋值初始化。
2、generate_object_layers()生成对象层高数据
cpp
std::vector<coordf_t> generate_object_layers(
const SlicingParameters &slicing_params,
const std::vector<coordf_t> &layer_height_profile,
bool is_precise_z_height)
{
assert(! layer_height_profile.empty());
coordf_t print_z = 0;
coordf_t height = 0;
std::vector<coordf_t> out;
if (slicing_params.first_object_layer_height_fixed()) {
out.push_back(0);
print_z = slicing_params.first_object_layer_height;
out.push_back(print_z);
}
size_t idx_layer_height_profile = 0;
// loop until we have at least one layer and the max slice_z reaches the object height
coordf_t slice_z = print_z + 0.5 * slicing_params.min_layer_height;
while (slice_z < slicing_params.object_print_z_height()) {
height = slicing_params.min_layer_height;
if (idx_layer_height_profile < layer_height_profile.size()) {
size_t next = idx_layer_height_profile + 2;
for (;;) {
if (next >= layer_height_profile.size() || slice_z < layer_height_profile[next])
break;
idx_layer_height_profile = next;
next += 2;
}
coordf_t z1 = layer_height_profile[idx_layer_height_profile];
coordf_t h1 = layer_height_profile[idx_layer_height_profile + 1];
height = h1;
if (next < layer_height_profile.size()) {
coordf_t z2 = layer_height_profile[next];
coordf_t h2 = layer_height_profile[next + 1];
height = lerp(h1, h2, (slice_z - z1) / (z2 - z1));
assert(height >= slicing_params.min_layer_height - EPSILON && height <= slicing_params.max_layer_height + EPSILON);
}
}
slice_z = print_z + 0.5 * height;
if (slice_z >= slicing_params.object_print_z_height())
break;
assert(height > slicing_params.min_layer_height - EPSILON);
assert(height < slicing_params.max_layer_height + EPSILON);
out.push_back(print_z);
print_z += height;
slice_z = print_z + 0.5 * slicing_params.min_layer_height;
out.push_back(print_z);
}
if (is_precise_z_height)
adjust_layer_series_to_align_object_height(slicing_params, out);
return out;
}
此函数会对模型进行层高的分割。将每一层的边界数值通过std::vector<coordf_t> out进行返回。以层高为0.2毫米来说,保存的值为[0,0.2,0.2,0.4,0.4,0.6...]进行返回。
3、new_layers()创建Layer类对象
cpp
LayerPtrs new_layers(
PrintObject *print_object,
// Object layers (pairs of bottom/top Z coordinate), without the raft.
const std::vector<coordf_t> &object_layers)
{
LayerPtrs out;
out.reserve(object_layers.size());
auto id = int(print_object->slicing_parameters().raft_layers());
coordf_t zmin = print_object->slicing_parameters().object_print_z_min;
Layer *prev = nullptr;
for (size_t i_layer = 0; i_layer < object_layers.size(); i_layer += 2) {
coordf_t lo = object_layers[i_layer];
coordf_t hi = object_layers[i_layer + 1];
coordf_t slice_z = 0.5 * (lo + hi);
Layer *layer = new Layer(id ++, print_object, hi - lo, hi + zmin, slice_z);
out.emplace_back(layer);
if (prev != nullptr) {
prev->upper_layer = layer;
layer->lower_layer = prev;
}
prev = layer;
}
return out;
}
4、Layer 切片层类
cpp
class Layer
{
public:
// Sequential index of this layer in PrintObject::m_layers, offsetted by the number of raft layers.
size_t id() const { return m_id; }
void set_id(size_t id) { m_id = id; }
PrintObject* object() { return m_object; }
const PrintObject* object() const { return m_object; }
Layer *upper_layer;
Layer *lower_layer;
bool slicing_errors;
coordf_t slice_z; // Z used for slicing in unscaled coordinates
coordf_t print_z; // Z used for printing in unscaled coordinates
coordf_t height; // layer height in unscaled coordinates
coordf_t bottom_z() const { return this->print_z - this->height; }
// BBS
mutable ExPolygons sharp_tails;
mutable ExPolygons cantilevers;
mutable std::vector<float> sharp_tails_height;
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
// (with possibly differing extruder ID and slicing parameters) and merged.
// For the first layer, if the Elephant foot compensation is applied, this lslice is uncompensated, therefore
// it includes the Elephant foot effect, thus it corresponds to the shape of the printed 1st layer.
// These lslices aka islands are chained by the shortest traverse distance and this traversal
// order will be applied by the G-code generator to the extrusions fitting into these lslices.
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
ExPolygons lslices;
ExPolygons lslices_extrudable; // BBS: the extrudable part of lslices used for tree support
std::vector<BoundingBox> lslices_bboxes;
// BBS
ExPolygons loverhangs;
std::vector<std::pair<ExPolygon, int>> loverhangs_with_type;
BoundingBox loverhangs_bbox;
std::vector<LoopNode> loop_nodes;
size_t region_count() const { return m_regions.size(); }
const LayerRegion* get_region(int idx) const { return m_regions[idx]; }
LayerRegion* get_region(int idx) { return m_regions[idx]; }
LayerRegion* add_region(const PrintRegion *print_region);
const LayerRegionPtrs& regions() const { return m_regions; }
// Test whether whether there are any slices assigned to this layer.
bool empty() const;
void apply_auto_circle_compensation();
void make_slices();
// Backup and restore raw sliced regions if needed.
//FIXME Review whether not to simplify the code by keeping the raw_slices all the time.
void backup_untyped_slices();
void restore_untyped_slices();
// To improve robustness of detect_surfaces_type() when reslicing (working with typed slices), see GH issue #7442.
void restore_untyped_slices_no_extra_perimeters();
// Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices.
ExPolygons merged(float offset) const;
template <class T> bool any_internal_region_slice_contains(const T &item) const {
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_internal_contains(item)) return true;
return false;
}
template <class T> bool any_bottom_region_slice_contains(const T &item) const {
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_bottom_contains(item)) return true;
return false;
}
void make_perimeters();
//BBS
void calculate_perimeter_continuity(std::vector<LoopNode> &prev_nodes);
void recrod_cooling_node_for_each_extrusion();
// Phony version of make_fills() without parameters for Perl integration only.
void make_fills() { this->make_fills(nullptr, nullptr); }
void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator = nullptr);
Polylines generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree *adaptive_fill_octree,
FillAdaptive::Octree *support_fill_octree,
FillLightning::Generator* lightning_generator) const;
void make_ironing();
void export_region_slices_to_svg(const char *path) const;
void export_region_fill_surfaces_to_svg(const char *path) const;
// Export to "out/LayerRegion-name-%d.svg" with an increasing index with every export.
void export_region_slices_to_svg_debug(const char *name) const;
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
// Is there any valid extrusion assigned to this LayerRegion?
virtual bool has_extrusions() const { for (auto layerm : m_regions) if (layerm->has_extrusions()) return true; return false; }
//BBS
void simplify_wall_extrusion_path() { for (auto layerm : m_regions) layerm->simplify_wall_extrusion_entity();}
void simplify_infill_extrusion_path() { for (auto layerm : m_regions) layerm->simplify_infill_extrusion_entity(); }
//BBS: this function calculate the maximum void grid area of sparse infill of this layer. Just estimated value
coordf_t get_sparse_infill_max_void_area();
// FN_HIGHER_EQUAL: the provided object pointer has a Z value >= of an internal threshold.
// Find the first item with Z value >= of an internal threshold of fn_higher_equal.
// If no vec item with Z value >= of an internal threshold of fn_higher_equal is found, return vec.size()
// If the initial idx is size_t(-1), then use binary search.
// Otherwise search linearly upwards.
template<typename IteratorType, typename IndexType, typename FN_HIGHER_EQUAL>
static IndexType idx_higher_or_equal(IteratorType begin, IteratorType end, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal)
{
auto size = int(end - begin);
if (size == 0) {
idx = 0;
}
else if (idx == IndexType(-1)) {
// First of the batch of layers per thread pool invocation. Use binary search.
int idx_low = 0;
int idx_high = std::max(0, size - 1);
while (idx_low + 1 < idx_high) {
int idx_mid = (idx_low + idx_high) / 2;
if (fn_higher_equal(begin[idx_mid]))
idx_high = idx_mid;
else
idx_low = idx_mid;
}
idx = fn_higher_equal(begin[idx_low]) ? idx_low :
(fn_higher_equal(begin[idx_high]) ? idx_high : size);
}
else {
// For the other layers of this batch of layers, search incrementally, which is cheaper than the binary search.
while (int(idx) < size && !fn_higher_equal(begin[idx]))
++idx;
}
return idx;
}
size_t get_extruder_id(unsigned int filament_id) const;
protected:
friend class PrintObject;
friend std::vector<Layer*> new_layers(PrintObject*, const std::vector<coordf_t>&);
friend std::string fix_slicing_errors(PrintObject* object, LayerPtrs&, const std::function<void()>&, int &);
Layer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
upper_layer(nullptr), lower_layer(nullptr), slicing_errors(false),
slice_z(slice_z), print_z(print_z), height(height),
m_id(id), m_object(object) {}
virtual ~Layer();
//BBS: method to simplify support path
void simplify_support_entity_collection(ExtrusionEntityCollection* entity_collection);
void simplify_support_path(ExtrusionPath* path);
void simplify_support_multi_path(ExtrusionMultiPath* multipath);
void simplify_support_loop(ExtrusionLoop* loop);
private:
// Sequential index of layer, 0-based, offsetted by number of raft layers.
size_t m_id;
PrintObject *m_object;
LayerRegionPtrs m_regions;
};
成员变量:
m_id:从0开始计数,进行累加。
height:层高
print_z:开始打印的z坐标
slice_z:切片的z坐标,层最高最低边界位置的中间值
通过new_layers得到的指针数组,保存在PrintObject::m_layers中