Yet more refactoring of Print / PrintObject in regard to
C++11 loops, configuration and step invalidation.
This commit is contained in:
parent
0a692cc497
commit
c8b934f8d3
5 changed files with 155 additions and 202 deletions
|
@ -24,13 +24,10 @@ void Print::clear_objects()
|
||||||
|
|
||||||
void Print::delete_object(size_t idx)
|
void Print::delete_object(size_t idx)
|
||||||
{
|
{
|
||||||
PrintObject *object = this->objects[idx];
|
|
||||||
// before deleting object, invalidate all of its steps in order to
|
|
||||||
// invalidate all of the dependent ones in Print
|
|
||||||
object->invalidate_all_steps();
|
|
||||||
// destroy object and remove it from our container
|
// destroy object and remove it from our container
|
||||||
delete object;
|
delete this->objects[idx];
|
||||||
this->objects.erase(this->objects.begin() + idx);
|
this->objects.erase(this->objects.begin() + idx);
|
||||||
|
this->invalidate_all_steps();
|
||||||
// TODO: purge unused regions
|
// TODO: purge unused regions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +178,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
||||||
steps.emplace_back(psWipeTower);
|
steps.emplace_back(psWipeTower);
|
||||||
} else {
|
} else {
|
||||||
// for legacy, if we can't handle this option let's invalidate all steps
|
// for legacy, if we can't handle this option let's invalidate all steps
|
||||||
|
//FIXME invalidate all steps of all objects as well?
|
||||||
return this->invalidate_all_steps();
|
return this->invalidate_all_steps();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,8 +189,8 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
||||||
invalidated |= this->invalidate_step(step);
|
invalidated |= this->invalidate_step(step);
|
||||||
sort_remove_duplicates(osteps);
|
sort_remove_duplicates(osteps);
|
||||||
for (PrintObjectStep ostep : osteps)
|
for (PrintObjectStep ostep : osteps)
|
||||||
FOREACH_OBJECT(this, object)
|
for (PrintObject *object : this->objects)
|
||||||
invalidated |= (*object)->invalidate_step(ostep);
|
invalidated |= object->invalidate_step(ostep);
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,64 +290,42 @@ double Print::max_allowed_layer_height() const
|
||||||
return nozzle_diameter_max;
|
return nozzle_diameter_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller is responsible for supplying models whose objects don't collide
|
// Caller is responsible for supplying models whose objects don't collide
|
||||||
and have explicit instance positions */
|
// and have explicit instance positions.
|
||||||
void Print::add_model_object(ModelObject* model_object, int idx)
|
void Print::add_model_object(ModelObject* model_object, int idx)
|
||||||
{
|
{
|
||||||
DynamicPrintConfig object_config = model_object->config; // clone
|
// Initialize a new print object and store it at the given position.
|
||||||
object_config.normalize();
|
PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
||||||
|
|
||||||
// initialize print object and store it at the given position
|
|
||||||
PrintObject* o;
|
|
||||||
{
|
|
||||||
BoundingBoxf3 bb = model_object->raw_bounding_box();
|
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
// replacing existing object
|
delete this->objects[idx];
|
||||||
PrintObjectPtrs::iterator old_it = this->objects.begin() + idx;
|
this->objects[idx] = object;
|
||||||
// before deleting object, invalidate all of its steps in order to
|
} else
|
||||||
// invalidate all of the dependent ones in Print
|
this->objects.emplace_back(object);
|
||||||
(*old_it)->invalidate_all_steps();
|
// Invalidate all print steps.
|
||||||
delete *old_it;
|
this->invalidate_all_steps();
|
||||||
|
|
||||||
this->objects[idx] = o = new PrintObject(this, model_object, bb);
|
|
||||||
} else {
|
|
||||||
o = new PrintObject(this, model_object, bb);
|
|
||||||
this->objects.push_back(o);
|
|
||||||
|
|
||||||
// invalidate steps
|
|
||||||
this->invalidate_step(psSkirt);
|
|
||||||
this->invalidate_step(psBrim);
|
|
||||||
this->invalidate_step(psWipeTower);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) {
|
for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) {
|
||||||
ModelVolume* volume = model_object->volumes[volume_id];
|
// Get the config applied to this volume.
|
||||||
|
PrintRegionConfig config = this->_region_config_from_model_volume(*model_object->volumes[volume_id]);
|
||||||
// get the config applied to this volume
|
// Find an existing print region with the same config.
|
||||||
PrintRegionConfig config = this->_region_config_from_model_volume(*volume);
|
|
||||||
|
|
||||||
// find an existing print region with the same config
|
|
||||||
size_t region_id = size_t(-1);
|
size_t region_id = size_t(-1);
|
||||||
for (size_t i = 0; i < this->regions.size(); ++ i)
|
for (size_t i = 0; i < this->regions.size(); ++ i)
|
||||||
if (config.equals(this->regions[i]->config)) {
|
if (config.equals(this->regions[i]->config)) {
|
||||||
region_id = i;
|
region_id = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// If no region exists with the same config, create a new one.
|
||||||
// if no region exists with the same config, create a new one
|
|
||||||
if (region_id == size_t(-1)) {
|
if (region_id == size_t(-1)) {
|
||||||
region_id = this->regions.size();
|
region_id = this->regions.size();
|
||||||
this->add_region()->config.apply(config);
|
this->add_region()->config.apply(config);
|
||||||
}
|
}
|
||||||
|
// Assign volume to a region.
|
||||||
// assign volume to region
|
object->add_region_volume(region_id, volume_id);
|
||||||
o->add_region_volume(region_id, volume_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply config to print object
|
// Apply config to print object.
|
||||||
o->config.apply(this->default_object_config);
|
object->config.apply(this->default_object_config);
|
||||||
o->config.apply(object_config, true);
|
normalize_and_apply_config(object->config, model_object->config);
|
||||||
|
|
||||||
// update placeholders
|
// update placeholders
|
||||||
{
|
{
|
||||||
|
@ -383,12 +359,10 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
// apply variables to placeholder parser
|
// apply variables to placeholder parser
|
||||||
this->placeholder_parser.apply_config(config);
|
this->placeholder_parser.apply_config(config);
|
||||||
|
|
||||||
bool invalidated = false;
|
|
||||||
|
|
||||||
// handle changes to print config
|
// handle changes to print config
|
||||||
t_config_option_keys print_diff = this->config.diff(config);
|
t_config_option_keys print_diff = this->config.diff(config);
|
||||||
this->config.apply(config, print_diff, true);
|
this->config.apply(config, print_diff, true);
|
||||||
invalidated |= this->invalidate_state_by_config_options(print_diff);
|
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
||||||
|
|
||||||
// handle changes to object config defaults
|
// handle changes to object config defaults
|
||||||
this->default_object_config.apply(config, true);
|
this->default_object_config.apply(config, true);
|
||||||
|
@ -396,15 +370,8 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
// we don't assume that config contains a full ObjectConfig,
|
// we don't assume that config contains a full ObjectConfig,
|
||||||
// so we base it on the current print-wise default
|
// so we base it on the current print-wise default
|
||||||
PrintObjectConfig new_config = this->default_object_config;
|
PrintObjectConfig new_config = this->default_object_config;
|
||||||
new_config.apply(config, true);
|
|
||||||
|
|
||||||
// we override the new config with object-specific options
|
// we override the new config with object-specific options
|
||||||
{
|
normalize_and_apply_config(new_config, object->model_object()->config);
|
||||||
DynamicPrintConfig model_object_config = object->model_object()->config;
|
|
||||||
model_object_config.normalize();
|
|
||||||
new_config.apply(model_object_config, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check whether the new config is different from the current one
|
// check whether the new config is different from the current one
|
||||||
t_config_option_keys diff = object->config.diff(new_config);
|
t_config_option_keys diff = object->config.diff(new_config);
|
||||||
object->config.apply(new_config, diff, true);
|
object->config.apply(new_config, diff, true);
|
||||||
|
@ -417,56 +384,57 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
// All regions now have distinct settings.
|
// All regions now have distinct settings.
|
||||||
// Check whether applying the new region config defaults we'd get different regions.
|
// Check whether applying the new region config defaults we'd get different regions.
|
||||||
bool rearrange_regions = false;
|
bool rearrange_regions = false;
|
||||||
|
{
|
||||||
|
// Collect the already visited region configs into other_region_configs,
|
||||||
|
// so one may check for duplicates.
|
||||||
std::vector<PrintRegionConfig> other_region_configs;
|
std::vector<PrintRegionConfig> other_region_configs;
|
||||||
for (size_t region_id = 0; region_id < this->regions.size(); ++ region_id)
|
for (size_t region_id = 0; region_id < this->regions.size(); ++ region_id) {
|
||||||
{
|
PrintRegion ®ion = *this->regions[region_id];
|
||||||
PrintRegion* region = this->regions[region_id];
|
PrintRegionConfig this_region_config;
|
||||||
std::vector<PrintRegionConfig> this_region_configs;
|
bool this_region_config_set = false;
|
||||||
for (PrintObject* object : this->objects)
|
for (PrintObject *object : this->objects) {
|
||||||
{
|
if (region_id < object->region_volumes.size()) {
|
||||||
for (int volume_id : object->region_volumes[region_id]) {
|
for (int volume_id : object->region_volumes[region_id]) {
|
||||||
ModelVolume* volume = object->model_object()->volumes.at(volume_id);
|
const ModelVolume &volume = *object->model_object()->volumes[volume_id];
|
||||||
|
if (this_region_config_set) {
|
||||||
PrintRegionConfig new_config = this->_region_config_from_model_volume(*volume);
|
// If the new config for this volume differs from the other
|
||||||
|
|
||||||
for (const PrintRegionConfig &cfg : this_region_configs) {
|
|
||||||
// if the new config for this volume differs from the other
|
|
||||||
// volume configs currently associated to this region, it means
|
// volume configs currently associated to this region, it means
|
||||||
// the region subdivision does not make sense anymore
|
// the region subdivision does not make sense anymore.
|
||||||
if (! cfg.equals(new_config)) {
|
if (! this_region_config.equals(this->_region_config_from_model_volume(volume))) {
|
||||||
rearrange_regions = true;
|
rearrange_regions = true;
|
||||||
goto NEXT_REGION;
|
goto exit_for_rearrange_regions;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
this_region_config = this->_region_config_from_model_volume(volume);
|
||||||
|
this_region_config_set = true;
|
||||||
}
|
}
|
||||||
this_region_configs.push_back(new_config);
|
|
||||||
|
|
||||||
for (const PrintRegionConfig &cfg : other_region_configs) {
|
for (const PrintRegionConfig &cfg : other_region_configs) {
|
||||||
// if the new config for this volume equals any of the other
|
// If the new config for this volume equals any of the other
|
||||||
// volume configs that are not currently associated to this
|
// volume configs that are not currently associated to this
|
||||||
// region, it means the region subdivision does not make
|
// region, it means the region subdivision does not make
|
||||||
// sense anymore
|
// sense anymore.
|
||||||
if (cfg.equals(new_config)) {
|
if (cfg.equals(this_region_config)) {
|
||||||
rearrange_regions = true;
|
rearrange_regions = true;
|
||||||
goto NEXT_REGION;
|
goto exit_for_rearrange_regions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// if we're here and the new region config is different from the old
|
}
|
||||||
// one, we need to apply the new config and invalidate all objects
|
}
|
||||||
// (possible optimization: only invalidate objects using this region)
|
if (this_region_config_set) {
|
||||||
t_config_option_keys diff = region->config.diff(new_config);
|
t_config_option_keys diff = region.config.diff(this_region_config);
|
||||||
if (! diff.empty()) {
|
if (! diff.empty()) {
|
||||||
region->config.apply(new_config, diff);
|
region.config.apply(this_region_config, diff);
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : this->objects)
|
||||||
|
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
|
||||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
invalidated |= object->invalidate_state_by_config_options(diff);
|
||||||
}
|
}
|
||||||
|
other_region_configs.emplace_back(this_region_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(other_region_configs, this_region_configs);
|
|
||||||
|
|
||||||
NEXT_REGION:
|
exit_for_rearrange_regions:
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rearrange_regions) {
|
if (rearrange_regions) {
|
||||||
// The current subdivision of regions does not make sense anymore.
|
// The current subdivision of regions does not make sense anymore.
|
||||||
|
@ -518,56 +486,44 @@ bool Print::has_skirt() const
|
||||||
std::string Print::validate() const
|
std::string Print::validate() const
|
||||||
{
|
{
|
||||||
if (this->config.complete_objects) {
|
if (this->config.complete_objects) {
|
||||||
// check horizontal clearance
|
// Check horizontal clearance.
|
||||||
{
|
{
|
||||||
Polygons a;
|
Polygons convex_hulls_other;
|
||||||
FOREACH_OBJECT(this, i_object) {
|
for (PrintObject *object : this->objects) {
|
||||||
PrintObject* object = *i_object;
|
// Get convex hull of all meshes assigned to this print object
|
||||||
|
// (this is the same as model_object()->raw_mesh.convex_hull()
|
||||||
/* get convex hull of all meshes assigned to this print object
|
// but probably more efficient.
|
||||||
(this is the same as model_object()->raw_mesh.convex_hull()
|
|
||||||
but probably more efficient */
|
|
||||||
Polygon convex_hull;
|
Polygon convex_hull;
|
||||||
{
|
{
|
||||||
Polygons mesh_convex_hulls;
|
Polygons mesh_convex_hulls;
|
||||||
for (size_t i = 0; i < this->regions.size(); ++i) {
|
for (const std::vector<int> &volumes : object->region_volumes)
|
||||||
for (std::vector<int>::const_iterator it = object->region_volumes[i].begin(); it != object->region_volumes[i].end(); ++it) {
|
for (int volume_id : volumes)
|
||||||
Polygon hull = object->model_object()->volumes[*it]->mesh.convex_hull();
|
mesh_convex_hulls.emplace_back(object->model_object()->volumes[volume_id]->mesh.convex_hull());
|
||||||
mesh_convex_hulls.push_back(hull);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// make a single convex hull for all of them
|
// make a single convex hull for all of them
|
||||||
convex_hull = Slic3r::Geometry::convex_hull(mesh_convex_hulls);
|
convex_hull = Slic3r::Geometry::convex_hull(mesh_convex_hulls);
|
||||||
}
|
}
|
||||||
|
// Apply the same transformations we apply to the actual meshes when slicing them.
|
||||||
// apply the same transformations we apply to the actual meshes when slicing them
|
|
||||||
object->model_object()->instances.front()->transform_polygon(&convex_hull);
|
object->model_object()->instances.front()->transform_polygon(&convex_hull);
|
||||||
|
// Grow convex hull with the clearance margin.
|
||||||
// grow convex hull with the clearance margin
|
|
||||||
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
|
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
|
||||||
|
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||||
// now we check that no instance of convex_hull intersects any of the previously checked object instances
|
|
||||||
for (const Point © : object->_shifted_copies) {
|
for (const Point © : object->_shifted_copies) {
|
||||||
Polygon p = convex_hull;
|
Polygon p = convex_hull;
|
||||||
p.translate(copy);
|
p.translate(copy);
|
||||||
if (! intersection(a, p).empty())
|
if (! intersection(convex_hulls_other, p).empty())
|
||||||
return "Some objects are too close; your extruder will collide with them.";
|
return "Some objects are too close; your extruder will collide with them.";
|
||||||
polygons_append(a, p);
|
polygons_append(convex_hulls_other, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Check vertical clearance.
|
||||||
// check vertical clearance
|
|
||||||
{
|
{
|
||||||
std::vector<coord_t> object_height;
|
std::vector<coord_t> object_height;
|
||||||
FOREACH_OBJECT(this, i_object) {
|
for (const PrintObject *object : this->objects)
|
||||||
PrintObject* object = *i_object;
|
|
||||||
object_height.insert(object_height.end(), object->copies().size(), object->size.z);
|
object_height.insert(object_height.end(), object->copies().size(), object->size.z);
|
||||||
}
|
|
||||||
std::sort(object_height.begin(), object_height.end());
|
std::sort(object_height.begin(), object_height.end());
|
||||||
// ignore the tallest *copy* (this is why we repeat height for all of them):
|
// Ignore the tallest *copy* (this is why we repeat height for all of them):
|
||||||
// it will be printed as last one so its height doesn't matter
|
// it will be printed as last one so its height doesn't matter.
|
||||||
object_height.pop_back();
|
object_height.pop_back();
|
||||||
if (! object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value))
|
if (! object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value))
|
||||||
return "Some objects are too tall and cannot be printed without extruder collisions.";
|
return "Some objects are too tall and cannot be printed without extruder collisions.";
|
||||||
|
@ -576,7 +532,8 @@ std::string Print::validate() const
|
||||||
|
|
||||||
if (this->config.spiral_vase) {
|
if (this->config.spiral_vase) {
|
||||||
size_t total_copies_count = 0;
|
size_t total_copies_count = 0;
|
||||||
FOREACH_OBJECT(this, i_object) total_copies_count += (*i_object)->copies().size();
|
for (const PrintObject *object : this->objects)
|
||||||
|
total_copies_count += object->copies().size();
|
||||||
if (total_copies_count > 1)
|
if (total_copies_count > 1)
|
||||||
return "The Spiral Vase option can only be used when printing a single object.";
|
return "The Spiral Vase option can only be used when printing a single object.";
|
||||||
if (this->regions.size() > 1)
|
if (this->regions.size() > 1)
|
||||||
|
@ -594,9 +551,7 @@ std::string Print::validate() const
|
||||||
nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id));
|
nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id));
|
||||||
double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
|
double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
|
||||||
|
|
||||||
FOREACH_OBJECT(this, i_object) {
|
for (PrintObject *object : this->objects) {
|
||||||
PrintObject* object = *i_object;
|
|
||||||
|
|
||||||
if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) &&
|
if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) &&
|
||||||
(object->config.raft_layers > 0 || object->config.support_material.value)) {
|
(object->config.raft_layers > 0 || object->config.support_material.value)) {
|
||||||
// The object has some form of support and either support_material_extruder or support_material_interface_extruder
|
// The object has some form of support and either support_material_extruder or support_material_interface_extruder
|
||||||
|
@ -640,14 +595,11 @@ std::string Print::validate() const
|
||||||
BoundingBox Print::bounding_box() const
|
BoundingBox Print::bounding_box() const
|
||||||
{
|
{
|
||||||
BoundingBox bb;
|
BoundingBox bb;
|
||||||
FOREACH_OBJECT(this, object) {
|
for (const PrintObject *object : this->objects)
|
||||||
for (Points::const_iterator copy = (*object)->_shifted_copies.begin(); copy != (*object)->_shifted_copies.end(); ++copy) {
|
for (Point copy : object->_shifted_copies) {
|
||||||
bb.merge(*copy);
|
bb.merge(copy);
|
||||||
|
copy.translate(object->size);
|
||||||
Point p = *copy;
|
bb.merge(copy);
|
||||||
p.translate((*object)->size);
|
|
||||||
bb.merge(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
@ -737,25 +689,13 @@ Flow Print::skirt_flow() const
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume)
|
PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume)
|
||||||
{
|
{
|
||||||
PrintRegionConfig config = this->default_region_config;
|
PrintRegionConfig config = this->default_region_config;
|
||||||
{
|
normalize_and_apply_config(config, volume.get_object()->config);
|
||||||
DynamicPrintConfig other_config = volume.get_object()->config;
|
normalize_and_apply_config(config, volume.config);
|
||||||
other_config.normalize();
|
if (! volume.material_id().empty())
|
||||||
config.apply(other_config, true);
|
normalize_and_apply_config(config, volume.material()->config);
|
||||||
}
|
|
||||||
{
|
|
||||||
DynamicPrintConfig other_config = volume.config;
|
|
||||||
other_config.normalize();
|
|
||||||
config.apply(other_config, true);
|
|
||||||
}
|
|
||||||
if (!volume.material_id().empty()) {
|
|
||||||
DynamicPrintConfig material_config = volume.material()->config;
|
|
||||||
material_config.normalize();
|
|
||||||
config.apply(material_config, true);
|
|
||||||
}
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1039,9 +979,10 @@ std::string Print::output_filepath(const std::string &path)
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
// get the first input file name
|
// get the first input file name
|
||||||
std::string input_file;
|
std::string input_file;
|
||||||
FOREACH_OBJECT(this, object) {
|
for (const PrintObject *object : this->objects) {
|
||||||
input_file = (*object)->model_object()->input_file;
|
input_file = object->model_object()->input_file;
|
||||||
if (!input_file.empty()) break;
|
if (! input_file.empty())
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (boost::filesystem::path(input_file).parent_path() / this->output_filename()).string();
|
return (boost::filesystem::path(input_file).parent_path() / this->output_filename()).string();
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,10 +96,8 @@ class PrintObject
|
||||||
friend class Print;
|
friend class Print;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// map of (vectors of volume ids), indexed by region_id
|
// vector of (vectors of volume ids), indexed by region_id
|
||||||
/* (we use map instead of vector so that we don't have to worry about
|
std::vector<std::vector<int>> region_volumes;
|
||||||
resizing it and the [] operator adds new items automagically) */
|
|
||||||
std::map< size_t,std::vector<int> > region_volumes;
|
|
||||||
PrintObjectConfig config;
|
PrintObjectConfig config;
|
||||||
t_layer_height_ranges layer_height_ranges;
|
t_layer_height_ranges layer_height_ranges;
|
||||||
|
|
||||||
|
@ -146,7 +144,11 @@ public:
|
||||||
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), this->size); }
|
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), this->size); }
|
||||||
|
|
||||||
// adds region_id, too, if necessary
|
// adds region_id, too, if necessary
|
||||||
void add_region_volume(int region_id, int volume_id) { region_volumes[region_id].push_back(volume_id); }
|
void add_region_volume(int region_id, int volume_id) {
|
||||||
|
if (region_id >= region_volumes.size())
|
||||||
|
region_volumes.resize(region_id + 1);
|
||||||
|
region_volumes[region_id].push_back(volume_id);
|
||||||
|
}
|
||||||
// This is the *total* layer count (including support layers)
|
// This is the *total* layer count (including support layers)
|
||||||
// this value is not supposed to be compared with Layer::id
|
// this value is not supposed to be compared with Layer::id
|
||||||
// since they have different semantics.
|
// since they have different semantics.
|
||||||
|
|
|
@ -145,6 +145,13 @@ class DynamicPrintConfig : public PrintConfigBase, public DynamicConfig
|
||||||
void normalize();
|
void normalize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename CONFIG>
|
||||||
|
void normalize_and_apply_config(CONFIG &dst, const DynamicPrintConfig &src)
|
||||||
|
{
|
||||||
|
DynamicPrintConfig src_normalized = src;
|
||||||
|
src_normalized.normalize();
|
||||||
|
dst.apply(src_normalized, true);
|
||||||
|
}
|
||||||
|
|
||||||
class StaticPrintConfig : public PrintConfigBase, public StaticConfig
|
class StaticPrintConfig : public PrintConfigBase, public StaticConfig
|
||||||
{
|
{
|
||||||
|
|
|
@ -1107,14 +1107,14 @@ end:
|
||||||
std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::vector<float> &z, bool modifier)
|
std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::vector<float> &z, bool modifier)
|
||||||
{
|
{
|
||||||
std::vector<ExPolygons> layers;
|
std::vector<ExPolygons> layers;
|
||||||
assert(region_id < this->region_volumes.size());
|
if (region_id < this->region_volumes.size()) {
|
||||||
std::vector<int> &volumes = this->region_volumes[region_id];
|
std::vector<int> &volumes = this->region_volumes[region_id];
|
||||||
if (! volumes.empty()) {
|
if (! volumes.empty()) {
|
||||||
// Compose mesh.
|
// Compose mesh.
|
||||||
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
for (std::vector<int>::const_iterator it_volume = volumes.begin(); it_volume != volumes.end(); ++ it_volume) {
|
for (int volume_id : volumes) {
|
||||||
ModelVolume *volume = this->model_object()->volumes[*it_volume];
|
ModelVolume *volume = this->model_object()->volumes[volume_id];
|
||||||
if (volume->modifier == modifier)
|
if (volume->modifier == modifier)
|
||||||
mesh.merge(volume->mesh);
|
mesh.merge(volume->mesh);
|
||||||
}
|
}
|
||||||
|
@ -1130,6 +1130,7 @@ std::vector<ExPolygons> PrintObject::_slice_region(size_t region_id, const std::
|
||||||
mslicer.slice(z, &layers);
|
mslicer.slice(z, &layers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return layers;
|
return layers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,13 +162,15 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
||||||
|
|
||||||
// Evaluate the XY gap between the object outer perimeters and the support structures.
|
// Evaluate the XY gap between the object outer perimeters and the support structures.
|
||||||
coordf_t external_perimeter_width = 0.;
|
coordf_t external_perimeter_width = 0.;
|
||||||
for (std::map<size_t,std::vector<int>>::const_iterator it_region = object->region_volumes.begin(); it_region != object->region_volumes.end(); ++ it_region) {
|
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) {
|
||||||
const PrintRegionConfig &config = object->print()->get_region(it_region->first)->config;
|
if (! object->region_volumes[region_id].empty()) {
|
||||||
|
const PrintRegionConfig &config = object->print()->get_region(region_id)->config;
|
||||||
coordf_t width = config.external_perimeter_extrusion_width.get_abs_value(slicing_params.layer_height);
|
coordf_t width = config.external_perimeter_extrusion_width.get_abs_value(slicing_params.layer_height);
|
||||||
if (width <= 0.)
|
if (width <= 0.)
|
||||||
width = m_print_config->nozzle_diameter.get_at(config.perimeter_extruder-1);
|
width = m_print_config->nozzle_diameter.get_at(config.perimeter_extruder-1);
|
||||||
external_perimeter_width = std::max(external_perimeter_width, width);
|
external_perimeter_width = std::max(external_perimeter_width, width);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_gap_xy = m_object_config->support_material_xy_spacing.get_abs_value(external_perimeter_width);
|
m_gap_xy = m_object_config->support_material_xy_spacing.get_abs_value(external_perimeter_width);
|
||||||
|
|
||||||
m_can_merge_support_regions = m_object_config->support_material_extruder.value == m_object_config->support_material_interface_extruder.value;
|
m_can_merge_support_regions = m_object_config->support_material_extruder.value == m_object_config->support_material_interface_extruder.value;
|
||||||
|
|
Loading…
Reference in a new issue