Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2018-09-12 12:59:02 +0300
committerbubnikv <bubnikv@gmail.com>2018-09-12 12:59:02 +0300
commit0235f1a8211cfecf75ac0a585295bc1378747972 (patch)
tree9c1d06a43a691d9691c7eff6f21646b0dcc8cc74 /xs/src/libslic3r/PrintObject.cpp
parent41ce69f327a2fe3324dc47756b64a6fdb001cfa3 (diff)
parenta97df55592f524eb73bd7d04ef8b7c1b3525d27d (diff)
Merged with dev
Diffstat (limited to 'xs/src/libslic3r/PrintObject.cpp')
-rw-r--r--xs/src/libslic3r/PrintObject.cpp185
1 files changed, 154 insertions, 31 deletions
diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp
index ba2521cd7..96c831157 100644
--- a/xs/src/libslic3r/PrintObject.cpp
+++ b/xs/src/libslic3r/PrintObject.cpp
@@ -4,6 +4,7 @@
#include "Geometry.hpp"
#include "SupportMaterial.hpp"
#include "Surface.hpp"
+#include "Slicing.hpp"
#include <utility>
#include <boost/log/trivial.hpp>
@@ -37,6 +38,7 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
typed_slices(false),
m_print(print),
m_model_object(model_object),
+ size(Vec3crd::Zero()),
layer_height_profile_valid(false)
{
// Compute the translation to be applied to our meshes so that we work with smaller coordinates
@@ -47,10 +49,9 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
// don't assume it's already aligned and we don't alter the original position in model.
// We store the XY translation so that we can place copies correctly in the output G-code
// (copies are expressed in G-code coordinates and this translation is not publicly exposed).
- this->_copies_shift = Point::new_scale(modobj_bbox.min.x, modobj_bbox.min.y);
+ m_copies_shift = Point::new_scale(modobj_bbox.min(0), modobj_bbox.min(1));
// Scale the object size and store it
- Pointf3 size = modobj_bbox.size();
- this->size = Point3::new_scale(size.x, size.y, size.z);
+ this->size = (modobj_bbox.size() * (1. / SCALING_FACTOR)).cast<coord_t>();
}
this->reload_model_instances();
@@ -58,10 +59,10 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding
this->layer_height_profile = model_object->layer_height_profile;
}
-bool PrintObject::add_copy(const Pointf &point)
+bool PrintObject::add_copy(const Vec2d &point)
{
Points points = m_copies;
- points.push_back(Point::new_scale(point.x, point.y));
+ points.push_back(Point::new_scale(point(0), point(1)));
return this->set_copies(points);
}
@@ -74,24 +75,23 @@ bool PrintObject::delete_last_copy()
bool PrintObject::set_copies(const Points &points)
{
- m_copies = points;
+ bool copies_num_changed = m_copies.size() != points.size();
// order copies with a nearest neighbor search and translate them by _copies_shift
- this->_shifted_copies.clear();
- this->_shifted_copies.reserve(points.size());
+ m_copies.clear();
+ m_copies.reserve(points.size());
// order copies with a nearest-neighbor search
std::vector<Points::size_type> ordered_copies;
Slic3r::Geometry::chained_path(points, ordered_copies);
- for (size_t point_idx : ordered_copies) {
- Point copy = points[point_idx];
- copy.translate(this->_copies_shift);
- this->_shifted_copies.push_back(copy);
- }
+ for (size_t point_idx : ordered_copies)
+ m_copies.push_back(points[point_idx] + m_copies_shift);
bool invalidated = m_print->invalidate_step(psSkirt);
invalidated |= m_print->invalidate_step(psBrim);
+ if (copies_num_changed)
+ invalidated |= m_print->invalidate_step(psWipeTower);
return invalidated;
}
@@ -100,7 +100,8 @@ bool PrintObject::reload_model_instances()
Points copies;
copies.reserve(m_model_object->instances.size());
for (const ModelInstance *mi : m_model_object->instances)
- copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y));
+ if (mi->is_printable())
+ copies.emplace_back(Point::new_scale(mi->offset(0), mi->offset(1)));
return this->set_copies(copies);
}
@@ -115,7 +116,7 @@ bool PrintObject::reload_model_instances()
// this should be idempotent
void PrintObject::slice()
{
- if (m_state.is_done(posSlice))
+ if (this->is_step_done(posSlice))
return;
this->set_started(posSlice);
m_print->set_status(10, "Processing triangulated mesh");
@@ -143,7 +144,7 @@ void PrintObject::make_perimeters()
// prerequisites
this->slice();
- if (m_state.is_done(posPerimeters))
+ if (this->is_step_done(posPerimeters))
return;
this->set_started(posPerimeters);
@@ -168,12 +169,8 @@ void PrintObject::make_perimeters()
// inside the object - infill_only_where_needed should be the method of choice for printing
// hollow objects
for (size_t region_id = 0; region_id < m_print->regions().size(); ++ region_id) {
- const PrintRegion &region = *m_print->regions()[region_id];
-
- if (!region.config().extra_perimeters
- || region.config().perimeters == 0
- || region.config().fill_density == 0
- || this->layer_count() < 2)
+ const PrintRegion &region = *m_print->regions()[region_id];
+ if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
continue;
BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start";
@@ -259,7 +256,7 @@ void PrintObject::make_perimeters()
void PrintObject::prepare_infill()
{
- if (m_state.is_done(posPrepareInfill))
+ if (this->is_step_done(posPrepareInfill))
return;
this->set_started(posPrepareInfill);
@@ -375,10 +372,13 @@ void PrintObject::prepare_infill()
void PrintObject::infill()
{
+ if (! this->is_printable())
+ return;
+
// prerequisites
this->prepare_infill();
- if (! m_state.is_done(posInfill)) {
+ if (! this->is_step_done(posInfill)) {
this->set_started(posInfill);
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
tbb::parallel_for(
@@ -401,7 +401,7 @@ void PrintObject::infill()
void PrintObject::generate_support_material()
{
- if (! m_state.is_done(posSupportMaterial)) {
+ if (! this->is_step_done(posSupportMaterial)) {
this->set_started(posSupportMaterial);
this->clear_support_layers();
if ((m_config.support_material || m_config.raft_layers > 0) && m_layers.size() > 1) {
@@ -545,7 +545,10 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "perimeter_speed"
|| opt_key == "small_perimeter_speed"
|| opt_key == "solid_infill_speed"
- || opt_key == "top_solid_infill_speed") {
+ || opt_key == "top_solid_infill_speed"
+ || opt_key == "wipe_into_infill" // when these these two are changed, we only need to invalidate the wipe tower,
+ || opt_key == "wipe_into_objects" // which we already did at the very beginning - nothing more to be done
+ ) {
// these options only affect G-code export, so nothing to invalidate
} else {
// for legacy, if we can't handle this option let's invalidate all steps
@@ -585,6 +588,8 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
}
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
+ // It also decides about what the wipe_into_infill / wipe_into_object features will do,
+ // and that too depends on many of the settings.
invalidated |= m_print->invalidate_step(psWipeTower);
return invalidated;
}
@@ -1341,7 +1346,7 @@ SlicingParameters PrintObject::slicing_parameters() const
{
return SlicingParameters::create_from_config(
this->print()->config(), m_config,
- unscale(this->size.z), this->print()->object_extruders());
+ unscale<double>(this->size(2)), this->print()->object_extruders());
}
bool PrintObject::update_layer_height_profile(std::vector<coordf_t> &layer_height_profile) const
@@ -1402,8 +1407,8 @@ void PrintObject::_slice()
this->typed_slices = false;
-#if 0
- // Disable parallelization for debugging purposes.
+#ifdef SLIC3R_PROFILE
+ // Disable parallelization so the Shiny profiler works
static tbb::task_scheduler_init *tbb_init = nullptr;
tbb_init = new tbb::task_scheduler_init(1);
#endif
@@ -1461,7 +1466,7 @@ void PrintObject::_slice()
if (region_id == other_region_id)
continue;
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) {
- Layer *layer = this->layers()[layer_id];
+ Layer *layer = m_layers[layer_id];
LayerRegion *layerm = layer->m_regions[region_id];
LayerRegion *other_layerm = layer->m_regions[other_region_id];
if (layerm == nullptr || other_layerm == nullptr)
@@ -1563,7 +1568,7 @@ std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::
// consider the first one
this->model_object()->instances.front()->transform_mesh(&mesh, true);
// align mesh to Z = 0 (it should be already aligned actually) and apply XY shift
- mesh.translate(- float(unscale(this->_copies_shift.x)), - float(unscale(this->_copies_shift.y)), -float(this->model_object()->bounding_box().min.z));
+ mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), - float(this->model_object()->bounding_box().min(2)));
// perform actual slicing
TriangleMeshSlicer mslicer;
Print *print = this->print();
@@ -1680,6 +1685,113 @@ void PrintObject::_simplify_slices(double distance)
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - end";
}
+void PrintObject::_make_perimeters()
+{
+ if (!this->is_printable())
+ return;
+
+ if (this->is_step_done(posPerimeters))
+ return;
+ this->set_started(posPerimeters);
+
+ BOOST_LOG_TRIVIAL(info) << "Generating perimeters...";
+
+ // merge slices if they were split into types
+ if (this->typed_slices) {
+ FOREACH_LAYER(this, layer_it)
+ (*layer_it)->merge_slices();
+ this->typed_slices = false;
+ this->invalidate_step(posPrepareInfill);
+ }
+
+ // compare each layer to the one below, and mark those slices needing
+ // one additional inner perimeter, like the top of domed objects-
+
+ // this algorithm makes sure that at least one perimeter is overlapping
+ // but we don't generate any extra perimeter if fill density is zero, as they would be floating
+ // inside the object - infill_only_where_needed should be the method of choice for printing
+ // hollow objects
+ for (size_t region_id = 0; region_id < m_print->regions().size(); ++ region_id) {
+ const PrintRegion &region = *m_print->regions()[region_id];
+ if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
+ continue;
+
+ BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start";
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, m_layers.size() - 1),
+ [this, &region, region_id](const tbb::blocked_range<size_t>& range) {
+ for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
+ LayerRegion &layerm = *m_layers[layer_idx]->regions()[region_id];
+ const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->regions()[region_id];
+ const Polygons upper_layerm_polygons = upper_layerm.slices;
+ // Filter upper layer polygons in intersection_ppl by their bounding boxes?
+ // my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
+ const double total_loop_length = total_length(upper_layerm_polygons);
+ const coord_t perimeter_spacing = layerm.flow(frPerimeter).scaled_spacing();
+ const Flow ext_perimeter_flow = layerm.flow(frExternalPerimeter);
+ const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width();
+ const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing();
+
+ for (Surface &slice : layerm.slices.surfaces) {
+ for (;;) {
+ // compute the total thickness of perimeters
+ const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2
+ + (region.config().perimeters-1 + slice.extra_perimeters) * perimeter_spacing;
+ // define a critical area where we don't want the upper slice to fall into
+ // (it should either lay over our perimeters or outside this area)
+ const coord_t critical_area_depth = coord_t(perimeter_spacing * 1.5);
+ const Polygons critical_area = diff(
+ offset(slice.expolygon, float(- perimeters_thickness)),
+ offset(slice.expolygon, float(- perimeters_thickness - critical_area_depth))
+ );
+ // check whether a portion of the upper slices falls inside the critical area
+ const Polylines intersection = intersection_pl(to_polylines(upper_layerm_polygons), critical_area);
+ // only add an additional loop if at least 30% of the slice loop would benefit from it
+ if (total_length(intersection) <= total_loop_length*0.3)
+ break;
+ /*
+ if (0) {
+ require "Slic3r/SVG.pm";
+ Slic3r::SVG::output(
+ "extra.svg",
+ no_arrows => 1,
+ expolygons => union_ex($critical_area),
+ polylines => [ map $_->split_at_first_point, map $_->p, @{$upper_layerm->slices} ],
+ );
+ }
+ */
+ ++ slice.extra_perimeters;
+ }
+ #ifdef DEBUG
+ if (slice.extra_perimeters > 0)
+ printf(" adding %d more perimeter(s) at layer %zu\n", slice.extra_perimeters, layer_idx);
+ #endif
+ }
+ }
+ });
+ BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - end";
+ }
+
+ BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start";
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, m_layers.size()),
+ [this](const tbb::blocked_range<size_t>& range) {
+ for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
+ m_layers[layer_idx]->make_perimeters();
+ }
+ );
+ BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end";
+
+ /*
+ simplify slices (both layer and region slices),
+ we only need the max resolution for perimeters
+ ### This makes this method not-idempotent, so we keep it disabled for now.
+ ###$self->_simplify_slices(&Slic3r::SCALED_RESOLUTION);
+ */
+
+ this->set_done(posPerimeters);
+}
+
// Only active if config->infill_only_where_needed. This step trims the sparse infill,
// so it acts as an internal support. It maintains all other infill types intact.
// Here the internal surfaces and perimeters have to be supported by the sparse infill.
@@ -2069,6 +2181,9 @@ void PrintObject::combine_infill()
void PrintObject::_generate_support_material()
{
+ if (!this->is_printable())
+ return;
+
PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
support_material.generate(*this);
}
@@ -2083,4 +2198,12 @@ void PrintObject::reset_layer_height_profile()
this->model_object()->layer_height_profile_valid = false;
}
+void PrintObject::adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
+{
+ update_layer_height_profile(m_model_object->layer_height_profile);
+ Slic3r::adjust_layer_height_profile(slicing_parameters(), m_model_object->layer_height_profile, z, layer_thickness_delta, band_width, LayerHeightEditActionType(action));
+ m_model_object->layer_height_profile_valid = true;
+ layer_height_profile_valid = false;
+}
+
} // namespace Slic3r