raft layers, partial objects memory, params acceleration
This commit is contained in:
parent
f2deefd1de
commit
41f1b83ae4
@ -427,9 +427,10 @@ void PrintObject::generate_support_spots()
|
|||||||
BOOST_LOG_TRIVIAL(debug) << "Searching support spots - start";
|
BOOST_LOG_TRIVIAL(debug) << "Searching support spots - start";
|
||||||
m_print->set_status(75, L("Searching support spots"));
|
m_print->set_status(75, L("Searching support spots"));
|
||||||
if (!this->shared_regions()->generated_support_points.has_value()) {
|
if (!this->shared_regions()->generated_support_points.has_value()) {
|
||||||
PrintTryCancel cancel_func = m_print->make_try_cancel();
|
PrintTryCancel cancel_func = m_print->make_try_cancel();
|
||||||
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values};
|
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values,
|
||||||
SupportSpotsGenerator::SupportPoints supp_points = SupportSpotsGenerator::full_search(this, cancel_func, params);
|
float(this->print()->m_config.perimeter_acceleration.getFloat())};
|
||||||
|
auto [supp_points, partial_objects] = SupportSpotsGenerator::full_search(this, cancel_func, params);
|
||||||
this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points};
|
this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points};
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
}
|
}
|
||||||
@ -468,7 +469,8 @@ void PrintObject::estimate_curled_extrusions()
|
|||||||
|
|
||||||
// Estimate curling of support material and add it to the malformaition lines of each layer
|
// Estimate curling of support material and add it to the malformaition lines of each layer
|
||||||
float support_flow_width = support_material_flow(this, this->config().layer_height).width();
|
float support_flow_width = support_material_flow(this, this->config().layer_height).width();
|
||||||
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values};
|
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values,
|
||||||
|
float(this->print()->config().perimeter_acceleration.getFloat())};
|
||||||
SupportSpotsGenerator::estimate_supports_malformations(this->support_layers(), support_flow_width, params);
|
SupportSpotsGenerator::estimate_supports_malformations(this->support_layers(), support_flow_width, params);
|
||||||
SupportSpotsGenerator::estimate_malformations(this->layers(), params);
|
SupportSpotsGenerator::estimate_malformations(this->layers(), params);
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
|
@ -579,12 +579,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// return new object part and actual area covered by extrusions
|
// return new object part and actual area covered by extrusions
|
||||||
std::tuple<ObjectPart, float> build_object_part_from_slice(const LayerSlice &slice, const Layer *layer)
|
std::tuple<ObjectPart, float> build_object_part_from_slice(const LayerSlice &slice, const Layer *layer, const Params& params)
|
||||||
{
|
{
|
||||||
ObjectPart new_object_part;
|
ObjectPart new_object_part;
|
||||||
float area_covered_by_extrusions = 0;
|
float area_covered_by_extrusions = 0;
|
||||||
|
|
||||||
auto add_extrusions_to_object = [&new_object_part, &area_covered_by_extrusions](const ExtrusionEntity *e, const LayerRegion *region) {
|
auto add_extrusions_to_object = [&new_object_part, &area_covered_by_extrusions, ¶ms](const ExtrusionEntity *e,
|
||||||
|
const LayerRegion *region) {
|
||||||
float flow_width = get_flow_width(region, e->role());
|
float flow_width = get_flow_width(region, e->role());
|
||||||
const Layer *l = region->layer();
|
const Layer *l = region->layer();
|
||||||
float slice_z = l->slice_z;
|
float slice_z = l->slice_z;
|
||||||
@ -596,9 +597,9 @@ std::tuple<ObjectPart, float> build_object_part_from_slice(const LayerSlice &sli
|
|||||||
new_object_part.volume += volume;
|
new_object_part.volume += volume;
|
||||||
new_object_part.volume_centroid_accumulator += to_3d(Vec2f((line.a + line.b) / 2.0f), slice_z) * volume;
|
new_object_part.volume_centroid_accumulator += to_3d(Vec2f((line.a + line.b) / 2.0f), slice_z) * volume;
|
||||||
|
|
||||||
if (l->bottom_z() < EPSILON) { // layer attached on bed
|
if (l->id() == params.raft_layers_count) { // layer attached on bed/raft
|
||||||
new_object_part.connected_to_bed = true;
|
new_object_part.connected_to_bed = true;
|
||||||
float sticking_area = line.len * flow_width;
|
float sticking_area = line.len * flow_width;
|
||||||
new_object_part.sticking_area += sticking_area;
|
new_object_part.sticking_area += sticking_area;
|
||||||
Vec2f middle = Vec2f((line.a + line.b) / 2.0f);
|
Vec2f middle = Vec2f((line.a + line.b) / 2.0f);
|
||||||
new_object_part.sticking_centroid_accumulator += sticking_area * to_3d(middle, slice_z);
|
new_object_part.sticking_centroid_accumulator += sticking_area * to_3d(middle, slice_z);
|
||||||
@ -681,11 +682,12 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms)
|
std::tuple<SupportPoints, PartialObjects> check_stability(const PrintObject *po, const PrintTryCancel &cancel_func, const Params ¶ms)
|
||||||
{
|
{
|
||||||
SupportPoints supp_points{};
|
SupportPoints supp_points{};
|
||||||
SupportGridFilter supports_presence_grid(po, params.min_distance_between_support_points);
|
SupportGridFilter supports_presence_grid(po, params.min_distance_between_support_points);
|
||||||
ActiveObjectParts active_object_parts{};
|
ActiveObjectParts active_object_parts{};
|
||||||
|
PartialObjects partial_objects{};
|
||||||
LD prev_layer_ext_perim_lines;
|
LD prev_layer_ext_perim_lines;
|
||||||
|
|
||||||
std::unordered_map<size_t, size_t> prev_slice_idx_to_object_part_mapping;
|
std::unordered_map<size_t, size_t> prev_slice_idx_to_object_part_mapping;
|
||||||
@ -693,6 +695,14 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance
|
|||||||
std::unordered_map<size_t, SliceConnection> prev_slice_idx_to_weakest_connection;
|
std::unordered_map<size_t, SliceConnection> prev_slice_idx_to_weakest_connection;
|
||||||
std::unordered_map<size_t, SliceConnection> next_slice_idx_to_weakest_connection;
|
std::unordered_map<size_t, SliceConnection> next_slice_idx_to_weakest_connection;
|
||||||
|
|
||||||
|
auto remember_partial_object = [&active_object_parts, &partial_objects](size_t object_part_id) {
|
||||||
|
auto object_part = active_object_parts.access(object_part_id);
|
||||||
|
if (object_part.volume > EPSILON) {
|
||||||
|
partial_objects.emplace_back(object_part.volume_centroid_accumulator / object_part.volume, object_part.volume,
|
||||||
|
object_part.connected_to_bed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
for (size_t layer_idx = 0; layer_idx < po->layer_count(); ++layer_idx) {
|
for (size_t layer_idx = 0; layer_idx < po->layer_count(); ++layer_idx) {
|
||||||
cancel_func();
|
cancel_func();
|
||||||
const Layer *layer = po->get_layer(layer_idx);
|
const Layer *layer = po->get_layer(layer_idx);
|
||||||
@ -701,7 +711,7 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance
|
|||||||
|
|
||||||
for (size_t slice_idx = 0; slice_idx < layer->lslices_ex.size(); ++slice_idx) {
|
for (size_t slice_idx = 0; slice_idx < layer->lslices_ex.size(); ++slice_idx) {
|
||||||
const LayerSlice &slice = layer->lslices_ex.at(slice_idx);
|
const LayerSlice &slice = layer->lslices_ex.at(slice_idx);
|
||||||
auto [new_part, covered_area] = build_object_part_from_slice(slice, layer);
|
auto [new_part, covered_area] = build_object_part_from_slice(slice, layer, params);
|
||||||
SliceConnection connection_to_below = estimate_slice_connection(slice_idx, layer);
|
SliceConnection connection_to_below = estimate_slice_connection(slice_idx, layer);
|
||||||
|
|
||||||
#ifdef DETAILED_DEBUG_LOGS
|
#ifdef DETAILED_DEBUG_LOGS
|
||||||
@ -730,7 +740,10 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance
|
|||||||
|
|
||||||
final_part_id = *parts_ids.begin();
|
final_part_id = *parts_ids.begin();
|
||||||
for (size_t part_id : parts_ids) {
|
for (size_t part_id : parts_ids) {
|
||||||
if (final_part_id != part_id) { active_object_parts.merge(part_id, final_part_id); }
|
if (final_part_id != part_id) {
|
||||||
|
remember_partial_object(part_id);
|
||||||
|
active_object_parts.merge(part_id, final_part_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto estimate_conn_strength = [bottom_z](const SliceConnection &conn) {
|
auto estimate_conn_strength = [bottom_z](const SliceConnection &conn) {
|
||||||
@ -881,11 +894,16 @@ SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cance
|
|||||||
} // slice iterations
|
} // slice iterations
|
||||||
prev_layer_ext_perim_lines = LD(current_layer_ext_perims_lines);
|
prev_layer_ext_perim_lines = LD(current_layer_ext_perims_lines);
|
||||||
} // layer iterations
|
} // layer iterations
|
||||||
return supp_points;
|
|
||||||
|
for (const auto& active_obj_pair : prev_slice_idx_to_object_part_mapping) {
|
||||||
|
remember_partial_object(active_obj_pair.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {supp_points, partial_objects};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
void debug_export(SupportPoints support_points, std::string file_name)
|
void debug_export(const SupportPoints& support_points,const PartialObjects& objects, std::string file_name)
|
||||||
{
|
{
|
||||||
Slic3r::CNumericLocalesSetter locales_setter;
|
Slic3r::CNumericLocalesSetter locales_setter;
|
||||||
{
|
{
|
||||||
@ -910,19 +928,29 @@ void debug_export(SupportPoints support_points, std::string file_name)
|
|||||||
support_points[i].position(2), color[0], color[1], color[2]);
|
support_points[i].position(2), color[0], color[1], color[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < objects.size(); ++i) {
|
||||||
|
Vec3f color{1.0f, 0.0f, 1.0f};
|
||||||
|
if (objects[i].connected_to_bed) {
|
||||||
|
color = {1.0f, 0.0f, 0.0f};
|
||||||
|
}
|
||||||
|
fprintf(fp, "v %f %f %f %f %f %f\n", objects[i].centroid(0), objects[i].centroid(1), objects[i].centroid(2), color[0],
|
||||||
|
color[1], color[2]);
|
||||||
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SupportPoints full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms)
|
std::tuple<SupportPoints, PartialObjects> full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms)
|
||||||
{
|
{
|
||||||
SupportPoints supp_points = check_stability(po, cancel_func, params);
|
auto results = check_stability(po, cancel_func, params);
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
debug_export(supp_points, "issues");
|
auto [supp_points, objects] = results;
|
||||||
|
debug_export(supp_points, objects, "issues");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return supp_points;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width, const Params ¶ms)
|
void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width, const Params ¶ms)
|
||||||
|
@ -5,31 +5,38 @@
|
|||||||
#include "Line.hpp"
|
#include "Line.hpp"
|
||||||
#include "PrintBase.hpp"
|
#include "PrintBase.hpp"
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
namespace SupportSpotsGenerator {
|
namespace SupportSpotsGenerator {
|
||||||
|
|
||||||
struct Params {
|
struct Params
|
||||||
Params(const std::vector<std::string> &filament_types) {
|
{
|
||||||
|
Params(const std::vector<std::string> &filament_types, float max_acceleration, size_t raft_layers_count)
|
||||||
|
: max_acceleration(max_acceleration), raft_layers_count(raft_layers_count)
|
||||||
|
{
|
||||||
if (filament_types.size() > 1) {
|
if (filament_types.size() > 1) {
|
||||||
BOOST_LOG_TRIVIAL(warning)
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
|
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
|
||||||
}
|
}
|
||||||
if (filament_types.empty() || filament_types[0].empty()) {
|
if (filament_types.empty() || filament_types[0].empty()) {
|
||||||
BOOST_LOG_TRIVIAL(error)
|
BOOST_LOG_TRIVIAL(error) << "SupportSpotsGenerator error: empty filament_type";
|
||||||
<< "SupportSpotsGenerator error: empty filament_type";
|
|
||||||
filament_type = std::string("PLA");
|
filament_type = std::string("PLA");
|
||||||
} else {
|
} else {
|
||||||
filament_type = filament_types[0];
|
filament_type = filament_types[0];
|
||||||
BOOST_LOG_TRIVIAL(debug)
|
BOOST_LOG_TRIVIAL(debug) << "SupportSpotsGenerator: applying filament type: " << filament_type;
|
||||||
<< "SupportSpotsGenerator: applying filament type: " << filament_type;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
||||||
const float bridge_distance = 12.0f; //mm
|
const float bridge_distance = 12.0f; // mm
|
||||||
|
const float max_acceleration; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the
|
||||||
|
// jerk phase, so the usual machine limits are too low)
|
||||||
|
const size_t raft_layers_count;
|
||||||
|
std::string filament_type;
|
||||||
|
|
||||||
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.4, 1.2 };
|
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.4, 1.2 };
|
||||||
const float max_curled_height_factor = 10.0f;
|
const float max_curled_height_factor = 10.0f;
|
||||||
|
|
||||||
@ -37,9 +44,7 @@ struct Params {
|
|||||||
const float support_points_interface_radius = 1.5f; // mm
|
const float support_points_interface_radius = 1.5f; // mm
|
||||||
const float min_distance_to_allow_local_supports = 1.0f; //mm
|
const float min_distance_to_allow_local_supports = 1.0f; //mm
|
||||||
|
|
||||||
std::string filament_type;
|
|
||||||
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
||||||
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
|
|
||||||
const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important
|
const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important
|
||||||
const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials.
|
const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials.
|
||||||
const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... );
|
const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... );
|
||||||
@ -47,6 +52,10 @@ struct Params {
|
|||||||
|
|
||||||
// MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface
|
// MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface
|
||||||
double get_bed_adhesion_yield_strength() const {
|
double get_bed_adhesion_yield_strength() const {
|
||||||
|
if (raft_layers_count > 0) {
|
||||||
|
return get_support_spots_adhesion_strength();
|
||||||
|
}
|
||||||
|
|
||||||
if (filament_type == "PLA") {
|
if (filament_type == "PLA") {
|
||||||
return 0.018 * 1e6;
|
return 0.018 * 1e6;
|
||||||
} else if (filament_type == "PET" || filament_type == "PETG") {
|
} else if (filament_type == "PET" || filament_type == "PETG") {
|
||||||
@ -67,7 +76,7 @@ struct Params {
|
|||||||
enum class SupportPointCause {
|
enum class SupportPointCause {
|
||||||
LongBridge, // point generated on bridge extrusion longer than the allowed length
|
LongBridge, // point generated on bridge extrusion longer than the allowed length
|
||||||
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
|
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
|
||||||
FloatingExtrusion, // point generated on extrusion that does not hold on its own - huge overhangs
|
FloatingExtrusion, // point generated on extrusion that does not hold on its own
|
||||||
SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too small and there is a risk of separation (brim may help)
|
SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too small and there is a risk of separation (brim may help)
|
||||||
UnstableFloatingPart, // point generated for object parts not connected to the bed, holded only by the other support points (brim will not help here)
|
UnstableFloatingPart, // point generated for object parts not connected to the bed, holded only by the other support points (brim will not help here)
|
||||||
WeakObjectPart // point generated when some part of the object is too weak to hold the upper part and may break (imagine hourglass)
|
WeakObjectPart // point generated when some part of the object is too weak to hold the upper part and may break (imagine hourglass)
|
||||||
@ -118,8 +127,20 @@ struct Malformations {
|
|||||||
std::vector<Lines> layers; //for each layer
|
std::vector<Lines> layers; //for each layer
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::vector<size_t> quick_search(const PrintObject *po, const Params ¶ms);
|
struct PartialObject
|
||||||
SupportPoints full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms);
|
{
|
||||||
|
PartialObject(Vec3f centroid, float volume, bool connected_to_bed)
|
||||||
|
: centroid(centroid), volume(volume), connected_to_bed(connected_to_bed)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Vec3f centroid;
|
||||||
|
float volume;
|
||||||
|
bool connected_to_bed;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PartialObjects = std::vector<PartialObject>;
|
||||||
|
|
||||||
|
std::tuple<SupportPoints, PartialObjects> full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms);
|
||||||
|
|
||||||
void estimate_supports_malformations(std::vector<SupportLayer*> &layers, float supports_flow_width, const Params ¶ms);
|
void estimate_supports_malformations(std::vector<SupportLayer*> &layers, float supports_flow_width, const Params ¶ms);
|
||||||
void estimate_malformations(std::vector<Layer*> &layers, const Params ¶ms);
|
void estimate_malformations(std::vector<Layer*> &layers, const Params ¶ms);
|
||||||
|
Loading…
Reference in New Issue
Block a user