Skip to content

Commit

Permalink
fix crashes, improved slicing status & concurrency
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Jun 11, 2024
2 parents cfba10f + 7d2f06d commit a423f74
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 37 deletions.
6 changes: 3 additions & 3 deletions src/libslic3r/ExtrusionEntity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ bool ExtrusionLoop::split_at_vertex(const Point &point, const double scaled_epsi
p2.append(std::move(p1));
path->polyline.swap(p2); // swap points & fitting result
}
} else {
} else if (idx > 0 && idx < path->size() - 1) {
// new paths list starts with the second half of current path
ExtrusionPaths new_paths;
PolylineOrArc p1, p2;
Expand Down Expand Up @@ -236,8 +236,8 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const
const Point *p1 = this->paths[path_idx].polyline.get_points().data() + segment_idx;
const Point *p2 = p1;
++ p2;
double d2_1 = (point - *p1).cast<double>().squaredNorm();
double d2_2 = (point - *p2).cast<double>().squaredNorm();
double d2_1 = (p - *p1).cast<double>().squaredNorm();
double d2_2 = (p - *p2).cast<double>().squaredNorm();
const double thr2 = scaled_epsilon * scaled_epsilon;
if (d2_1 < d2_2) {
if (d2_1 < thr2)
Expand Down
24 changes: 19 additions & 5 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,11 +716,25 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
for(auto &t : temp) real_surface += t.area();
assert(compute_volume.volume < unscaled(unscaled(surface_fill.surface.area())) * surface_fill.params.layer_height + EPSILON);
double area = unscaled(unscaled(real_surface));
assert(compute_volume.volume <= area * surface_fill.params.layer_height * 1.001 || f->debug_verify_flow_mult <= 0.8);
if(compute_volume.volume > 0) //can fail for thin regions
assert(compute_volume.volume >= area * surface_fill.params.layer_height * 0.999 || f->debug_verify_flow_mult >= 1.3 || f->debug_verify_flow_mult == 0 // sawtooth output more filament,as it's 3D (debug_verify_flow_mult==0)
|| area < std::max(1.,surface_fill.params.config->solid_infill_below_area.value) || area < std::max(1.,surface_fill.params.config->solid_infill_below_layer_area.value));
}
if(surface_fill.surface.has_pos_top())
area *= surface_fill.params.config->fill_top_flow_ratio.value;
if(surface_fill.surface.has_pos_bottom() && f->layer_id == 0)
area *= surface_fill.params.config->first_layer_flow_ratio.value;
if(surface_fill.surface.has_mod_bridge() && f->layer_id == 0)
area *= surface_fill.params.config->first_layer_flow_ratio.value;
//TODO: over-bridge mod
if(surface_fill.params.config->over_bridge_flow_ratio.value == 1){
assert(compute_volume.volume <= area * surface_fill.params.layer_height * 1.001 || f->debug_verify_flow_mult <= 0.8);
if(compute_volume.volume > 0) //can fail for thin regions
assert(
compute_volume.volume >= area * surface_fill.params.layer_height * 0.999 ||
f->debug_verify_flow_mult >= 1.3 ||
f->debug_verify_flow_mult ==
0 // sawtooth output more filament,as it's 3D (debug_verify_flow_mult==0)
|| area < std::max(1., surface_fill.params.config->solid_infill_below_area.value) ||
area < std::max(1., surface_fill.params.config->solid_infill_below_layer_area.value));
}
}
#endif
}
}
Expand Down
39 changes: 35 additions & 4 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1905,6 +1905,9 @@ void GCode::_do_export(Print& print_mod, GCodeOutputStream &file, ThumbnailsGene
this->m_throw_if_canceled();

// Collect custom seam data from all objects.
print.set_status(0, L("Computing seam visibility areas: object %s / %s"),
{"1", std::to_string(print.objects().size())},
PrintBase::SlicingStatus::FORCE_SHOW | PrintBase::SlicingStatus::SECONDARY_STATE);
m_seam_placer.init(print, this->m_throw_if_canceled);

//activate first extruder is multi-extruder and not in start-gcode
Expand Down Expand Up @@ -3055,8 +3058,10 @@ LayerResult GCode::process_layer(
const Layer *object_layer = nullptr;
const SupportLayer *support_layer = nullptr;
const SupportLayer *raft_layer = nullptr;
const size_t layer_id = layers.front().layer()->id();
/*const*/ size_t layer_id = size_t(-1);
for (const LayerToPrint &l : layers) {
if(l.layer())
layer_id = l.layer()->id();
if (l.object_layer && ! object_layer)
object_layer = l.object_layer;
if (l.support_layer) {
Expand All @@ -3067,12 +3072,29 @@ LayerResult GCode::process_layer(
}
assert(l.layer() == nullptr || layer_id == l.layer()->id());
}
assert(layer_id < layer_count());
const Layer &layer = (object_layer != nullptr) ? *object_layer : *support_layer;
LayerResult result { {}, layer.id(), false, last_layer, false};
if (layer_tools.extruders.empty())
// Nothing to extrude.
return result;

if (object_layer) {
if (single_object_instance_idx != size_t(-1)) {
size_t nb_layers = object_layer->object()->layer_count();
m_object_sequentially_printed.insert(object_layer->object());
print.set_status(int((layer.id() * 100) / nb_layers),
std::string(L("Generating G-code layer %s / %s for object %s / %s")),
std::vector<std::string>{std::to_string(layer.id()), std::to_string(nb_layers), std::to_string(m_object_sequentially_printed.size()), std::to_string(print.num_object_instances())},
PrintBase::SlicingStatus::DEFAULT | PrintBase::SlicingStatus::SECONDARY_STATE);
} else {
print.set_status(int((layer.id() * 100) / layer_count()),
std::string(L("Generating G-code layer %s / %s")),
std::vector<std::string>{std::to_string(layer.id()), std::to_string(layer_count())},
PrintBase::SlicingStatus::DEFAULT | PrintBase::SlicingStatus::SECONDARY_STATE);
}
}

// Extract 1st object_layer and support_layer of this set of layers with an equal print_z.
coordf_t print_z = layer.print_z;
bool first_layer = layer_id == 0;
Expand Down Expand Up @@ -3764,9 +3786,6 @@ LayerResult GCode::process_layer(
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
log_memory_info();

if(object_layer)
print.set_status(int((layer.id() * 100) / layer_count()), std::string(L("Generating G-code layer %s / %s")), std::vector<std::string>{ std::to_string(layer.id()), std::to_string(layer_count()) }, PrintBase::SlicingStatus::DEFAULT | PrintBase::SlicingStatus::SECONDARY_STATE);

result.gcode = std::move(gcode);
result.cooling_buffer_flush = object_layer || raft_layer || last_layer;
return result;
Expand Down Expand Up @@ -4142,6 +4161,18 @@ void GCode::split_at_seam_pos(ExtrusionLoop& loop, bool was_clockwise)
if (loop.paths.empty())
return;

#if _DEBUG
ExtrusionLoop old_loop = loop;
for (const ExtrusionPath &path : loop.paths)
for (int i = 1; i < path.polyline.get_points().size(); ++i)
assert(!path.polyline.get_points()[i - 1].coincides_with_epsilon(path.polyline.get_points()[i]));
for (auto it = std::next(loop.paths.begin()); it != loop.paths.end(); ++it) {
assert(it->polyline.size() >= 2);
assert(std::prev(it)->polyline.back() == it->polyline.front());
}
assert(loop.first_point() == loop.last_point());
#endif

// SeamPosition seam_position = m_config.seam_position;
// if (loop.loop_role() == elrSkirt)
// seam_position = spNearest;
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/GCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ class GCode : ExtrusionVisitorConst {
std::string m_delayed_layer_change;
// Keeps track of the last extrusion role passed to the processor
ExtrusionRole m_last_processor_extrusion_role;
// For Progress bar indicator, in sequential mode (complete objects)
std::set<const PrintObject*> m_object_sequentially_printed;
// How many times will change_layer() be called?
// change_layer() will update the progress bar.
uint32_t m_layer_count;
Expand Down
7 changes: 6 additions & 1 deletion src/libslic3r/GCode/SeamPlacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1653,7 +1653,12 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
m_seam_per_object.clear();
this->external_perimeters_first = print.default_region_config().external_perimeters_first;

for (const PrintObject *po : print.objects()) {
for (size_t obj_idx = 0; obj_idx < print.objects().size(); ++ obj_idx) {
const PrintObject *po = print.objects()[obj_idx];
print.set_status(int((obj_idx * 100) / print.objects().size()),
("Computing seam visibility areas: object %s / %s"),
{std::to_string(obj_idx + 1), std::to_string(print.objects().size())},
PrintBase::SlicingStatus::SECONDARY_STATE);
throw_if_canceled_func();
SeamPosition configured_seam_preference = po->config().seam_position.value;
SeamComparator comparator { configured_seam_preference, *po };
Expand Down
10 changes: 5 additions & 5 deletions src/libslic3r/MultiPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,16 @@ int MultiPoint::find_point(const Point &point) const
return -1; // not found
}

int MultiPoint::find_point(const Point &point, double scaled_epsilon) const
int MultiPoint::find_point(const Point &point, coordf_t scaled_epsilon) const
{
if (scaled_epsilon == 0)
return this->find_point(point);

auto dist2_min = std::numeric_limits<double>::max();
auto eps2 = scaled_epsilon * scaled_epsilon;
int idx_min = -1;
coordf_t dist2_min = std::numeric_limits<coordf_t>::max();
coordf_t eps2 = scaled_epsilon * scaled_epsilon;
int idx_min = -1;
for (const Point &pt : this->points) {
double d2 = (pt - point).cast<double>().squaredNorm();
coordf_t d2 = pt.distance_to_square(point); //(pt - point).cast<coordf_t>().squaredNorm();
if (d2 < dist2_min) {
idx_min = int(&pt - &this->points.front());
dist2_min = d2;
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/MultiPoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class MultiPoint
int find_point(const Point &point) const;
// Return index of the closest point to point closer than scaled_epsilon.
// Return -1 if no such point exists.
int find_point(const Point &point, const double scaled_epsilon) const;
int find_point(const Point &point, const coordf_t scaled_epsilon) const;
bool has_boundary_point(const Point &point) const;
int closest_point_index(const Point &point) const {
int idx = -1;
Expand Down
10 changes: 5 additions & 5 deletions src/libslic3r/Point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,13 @@ class Point : public Vec2crd
Point projection_onto(const Line &line) const;
Point interpolate(const double percent, const Point &p) const;

double distance_to(const Point &point) const { return (point - *this).cast<double>().norm(); }
double distance_to_square(const Point &point) const {
double dx = double(point.x() - this->x());
double dy = double(point.y() - this->y());
coordf_t distance_to(const Point &point) const { return (point - *this).cast<coordf_t>().norm(); }
coordf_t distance_to_square(const Point &point) const {
coordf_t dx = double(point.x() - this->x());
coordf_t dy = double(point.y() - this->y());
return dx*dx + dy*dy;
}
double distance_to(const Line &line) const;
coordf_t distance_to(const Line &line) const;
bool coincides_with(const Point &point) const { return this->x() == point.x() && this->y() == point.y(); }
bool coincides_with_epsilon(const Point &point) const {
return std::abs(this->x() - point.x()) < SCALED_EPSILON/2 && std::abs(this->y() - point.y()) < SCALED_EPSILON/2;
Expand Down
5 changes: 3 additions & 2 deletions src/libslic3r/PrintBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,8 @@ class PrintBase : public ObjectBase
SLICING_ENDED = 1 << 6,
GCODE_ENDED = 1 << 7,
MAIN_STATE = 1 << 8,
SECONDARY_STATE = 1 << 9
SECONDARY_STATE = 1 << 9,
FORCE_SHOW = 1 << 10
};
// Bitmap of FlagBits
unsigned int flags;
Expand All @@ -443,7 +444,7 @@ class PrintBase : public ObjectBase
}
void set_status(int percent, const std::string& message, const std::vector<std::string>& args, unsigned int flags = SlicingStatus::DEFAULT) const {
//check if it need an update. Avoid doing a gui update each ms.
if ((flags & SlicingStatus::SECONDARY_STATE) != 0 && message != m_last_status_message) {
if ((flags & SlicingStatus::FORCE_SHOW) == 0 && (flags & SlicingStatus::SECONDARY_STATE) != 0 && message != m_last_status_message) {
std::chrono::time_point<std::chrono::system_clock> current_time = std::chrono::system_clock::now();
if ((static_cast<std::chrono::duration<double>>(current_time - PrintBase::m_last_status_update)).count() > 0.002 && PrintBase::m_last_status_percent != percent) {
PrintBase::m_last_status_update = current_time;
Expand Down
Loading

0 comments on commit a423f74

Please sign in to comment.