WIP PrintRegion refactoring: Another round of bug fixing, negative volumes
seem to work.
This commit is contained in:
parent
8ab6a615d0
commit
b3195614cf
7 changed files with 121 additions and 101 deletions
|
@ -2034,45 +2034,56 @@ bool model_object_list_extended(const Model &model_old, const Model &model_new)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type)
|
template<typename TypeFilterFn>
|
||||||
|
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, TypeFilterFn type_filter)
|
||||||
{
|
{
|
||||||
size_t i_old, i_new;
|
size_t i_old, i_new;
|
||||||
for (i_old = 0, i_new = 0; i_old < model_object_old.volumes.size() && i_new < model_object_new.volumes.size();) {
|
for (i_old = 0, i_new = 0; i_old < model_object_old.volumes.size() && i_new < model_object_new.volumes.size();) {
|
||||||
const ModelVolume &mv_old = *model_object_old.volumes[i_old];
|
const ModelVolume &mv_old = *model_object_old.volumes[i_old];
|
||||||
const ModelVolume &mv_new = *model_object_new.volumes[i_new];
|
const ModelVolume &mv_new = *model_object_new.volumes[i_new];
|
||||||
if (mv_old.type() != type) {
|
if (! type_filter(mv_old.type())) {
|
||||||
++ i_old;
|
++ i_old;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mv_new.type() != type) {
|
if (! type_filter(mv_new.type())) {
|
||||||
++ i_new;
|
++ i_new;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (mv_old.id() != mv_new.id())
|
if (mv_old.type() != mv_new.type() || mv_old.id() != mv_new.id())
|
||||||
return true;
|
return true;
|
||||||
//FIXME test for the content of the mesh!
|
//FIXME test for the content of the mesh!
|
||||||
|
if (! mv_old.get_matrix().isApprox(mv_new.get_matrix()))
|
||||||
if (!mv_old.get_matrix().isApprox(mv_new.get_matrix()))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
++ i_old;
|
++ i_old;
|
||||||
++ i_new;
|
++ i_new;
|
||||||
}
|
}
|
||||||
for (; i_old < model_object_old.volumes.size(); ++ i_old) {
|
for (; i_old < model_object_old.volumes.size(); ++ i_old) {
|
||||||
const ModelVolume &mv_old = *model_object_old.volumes[i_old];
|
const ModelVolume &mv_old = *model_object_old.volumes[i_old];
|
||||||
if (mv_old.type() == type)
|
if (type_filter(mv_old.type()))
|
||||||
// ModelVolume was deleted.
|
// ModelVolume was deleted.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (; i_new < model_object_new.volumes.size(); ++ i_new) {
|
for (; i_new < model_object_new.volumes.size(); ++ i_new) {
|
||||||
const ModelVolume &mv_new = *model_object_new.volumes[i_new];
|
const ModelVolume &mv_new = *model_object_new.volumes[i_new];
|
||||||
if (mv_new.type() == type)
|
if (type_filter(mv_new.type()))
|
||||||
// ModelVolume was added.
|
// ModelVolume was added.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type)
|
||||||
|
{
|
||||||
|
return model_volume_list_changed(model_object_old, model_object_new, [type](const ModelVolumeType t) { return t == type; });
|
||||||
|
}
|
||||||
|
|
||||||
|
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const std::initializer_list<ModelVolumeType> &types)
|
||||||
|
{
|
||||||
|
return model_volume_list_changed(model_object_old, model_object_new, [&types](const ModelVolumeType t) {
|
||||||
|
return std::find(types.begin(), types.end(), t) != types.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject& mo_new) {
|
bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject& mo_new) {
|
||||||
assert(! model_volume_list_changed(mo, mo_new, ModelVolumeType::MODEL_PART));
|
assert(! model_volume_list_changed(mo, mo_new, ModelVolumeType::MODEL_PART));
|
||||||
assert(mo.volumes.size() == mo_new.volumes.size());
|
assert(mo.volumes.size() == mo_new.volumes.size());
|
||||||
|
|
|
@ -1075,29 +1075,30 @@ private:
|
||||||
|
|
||||||
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
||||||
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
||||||
extern bool model_object_list_equal(const Model &model_old, const Model &model_new);
|
bool model_object_list_equal(const Model &model_old, const Model &model_new);
|
||||||
|
|
||||||
// Test whether the new model is just an extension of the old model (new objects were added
|
// Test whether the new model is just an extension of the old model (new objects were added
|
||||||
// to the end of the original list. In that case it is not necessary to kill the background processing.
|
// to the end of the original list. In that case it is not necessary to kill the background processing.
|
||||||
extern bool model_object_list_extended(const Model &model_old, const Model &model_new);
|
bool model_object_list_extended(const Model &model_old, const Model &model_new);
|
||||||
|
|
||||||
// Test whether the new ModelObject contains a different set of volumes (or sorted in a different order)
|
// Test whether the new ModelObject contains a different set of volumes (or sorted in a different order)
|
||||||
// than the old ModelObject.
|
// than the old ModelObject.
|
||||||
extern bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type);
|
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolumeType type);
|
||||||
|
bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const std::initializer_list<ModelVolumeType> &types);
|
||||||
|
|
||||||
// Test whether the now ModelObject has newer custom supports data than the old one.
|
// Test whether the now ModelObject has newer custom supports data than the old one.
|
||||||
// The function assumes that volumes list is synchronized.
|
// The function assumes that volumes list is synchronized.
|
||||||
extern bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject& mo_new);
|
bool model_custom_supports_data_changed(const ModelObject& mo, const ModelObject& mo_new);
|
||||||
|
|
||||||
// Test whether the now ModelObject has newer custom seam data than the old one.
|
// Test whether the now ModelObject has newer custom seam data than the old one.
|
||||||
// The function assumes that volumes list is synchronized.
|
// The function assumes that volumes list is synchronized.
|
||||||
extern bool model_custom_seam_data_changed(const ModelObject& mo, const ModelObject& mo_new);
|
bool model_custom_seam_data_changed(const ModelObject& mo, const ModelObject& mo_new);
|
||||||
|
|
||||||
// If the model has multi-part objects, then it is currently not supported by the SLA mode.
|
// If the model has multi-part objects, then it is currently not supported by the SLA mode.
|
||||||
// Either the model cannot be loaded, or a SLA printer has to be activated.
|
// Either the model cannot be loaded, or a SLA printer has to be activated.
|
||||||
extern bool model_has_multi_part_objects(const Model &model);
|
bool model_has_multi_part_objects(const Model &model);
|
||||||
// If the model has advanced features, then it cannot be processed in simple mode.
|
// If the model has advanced features, then it cannot be processed in simple mode.
|
||||||
extern bool model_has_advanced_features(const Model &model);
|
bool model_has_advanced_features(const Model &model);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
// Verify whether the IDs of Model / ModelObject / ModelVolume / ModelInstance / ModelMaterial are valid and unique.
|
||||||
|
|
|
@ -226,6 +226,7 @@ public:
|
||||||
void clear() {
|
void clear() {
|
||||||
all_regions.clear();
|
all_regions.clear();
|
||||||
layer_ranges.clear();
|
layer_ranges.clear();
|
||||||
|
cached_volume_ids.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -295,7 +295,7 @@ public:
|
||||||
std::abs(it->layer_height_range.first - range.first) > EPSILON ||
|
std::abs(it->layer_height_range.first - range.first) > EPSILON ||
|
||||||
std::abs(it->layer_height_range.second - range.second) > EPSILON )
|
std::abs(it->layer_height_range.second - range.second) > EPSILON )
|
||||||
return nullptr; // desired range doesn't found
|
return nullptr; // desired range doesn't found
|
||||||
return (it == m_ranges.end()) ? nullptr : it->config;
|
return it == m_ranges.end() ? nullptr : it->config;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LayerRange>::const_iterator begin() const { return m_ranges.cbegin(); }
|
std::vector<LayerRange>::const_iterator begin() const { return m_ranges.cbegin(); }
|
||||||
|
@ -442,7 +442,7 @@ private:
|
||||||
std::multiset<PrintObjectStatus> m_db;
|
std::multiset<PrintObjectStatus> m_db;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool model_volume_needs_bbox(const ModelVolume &mv)
|
static inline bool model_volume_solid_or_modifier(const ModelVolume &mv)
|
||||||
{
|
{
|
||||||
ModelVolumeType type = mv.type();
|
ModelVolumeType type = mv.type();
|
||||||
return type == ModelVolumeType::MODEL_PART || type == ModelVolumeType::NEGATIVE_VOLUME || type == ModelVolumeType::PARAMETER_MODIFIER;
|
return type == ModelVolumeType::MODEL_PART || type == ModelVolumeType::NEGATIVE_VOLUME || type == ModelVolumeType::PARAMETER_MODIFIER;
|
||||||
|
@ -590,7 +590,7 @@ void print_objects_regions_invalidate_keep_some_volumes(PrintObjectRegions &prin
|
||||||
|
|
||||||
const BoundingBoxf3* find_volume_extents(const PrintObjectRegions::LayerRangeRegions &layer_range, const ModelVolume &volume)
|
const BoundingBoxf3* find_volume_extents(const PrintObjectRegions::LayerRangeRegions &layer_range, const ModelVolume &volume)
|
||||||
{
|
{
|
||||||
auto it = lower_bound_by_predicate(layer_range.volumes.begin(), layer_range.volumes.end(), [&volume](const PrintObjectRegions::VolumeExtents &v){ return v.volume_id < volume.id(); });
|
auto it = lower_bound_by_predicate(layer_range.volumes.begin(), layer_range.volumes.end(), [&volume](const PrintObjectRegions::VolumeExtents &l){ return l.volume_id < volume.id(); });
|
||||||
return it != layer_range.volumes.end() && it->volume_id == volume.id() ? &it->bbox : nullptr;
|
return it != layer_range.volumes.end() && it->volume_id == volume.id() ? &it->bbox : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,27 +619,28 @@ bool verify_update_print_object_regions(
|
||||||
|
|
||||||
// Verify and / or update PrintRegions produced by ModelVolumes, layer range modifiers, modifier volumes.
|
// Verify and / or update PrintRegions produced by ModelVolumes, layer range modifiers, modifier volumes.
|
||||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
|
for (PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges)
|
||||||
for (PrintObjectRegions::VolumeRegion ®ion : layer_range.volume_regions) {
|
for (PrintObjectRegions::VolumeRegion ®ion : layer_range.volume_regions)
|
||||||
auto it_model_volume = lower_bound_by_predicate(model_volumes.begin(), model_volumes.end(), [®ion](const ModelVolume *v){ return v->id() < region.model_volume->id(); });
|
if (region.model_volume->is_model_part() || region.model_volume->is_modifier()) {
|
||||||
assert(it_model_volume != model_volumes.end() && (*it_model_volume)->id() == region.model_volume->id());
|
auto it_model_volume = lower_bound_by_predicate(model_volumes.begin(), model_volumes.end(), [®ion](const ModelVolume *l){ return l->id() < region.model_volume->id(); });
|
||||||
PrintRegionConfig cfg = region.parent == -1 ?
|
assert(it_model_volume != model_volumes.end() && (*it_model_volume)->id() == region.model_volume->id());
|
||||||
region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders) :
|
PrintRegionConfig cfg = region.parent == -1 ?
|
||||||
region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders);
|
region_config_from_model_volume(default_region_config, layer_range.config, **it_model_volume, num_extruders) :
|
||||||
if (cfg != region.region->config()) {
|
region_config_from_model_volume(layer_range.volume_regions[region.parent].region->config(), nullptr, **it_model_volume, num_extruders);
|
||||||
// Region configuration changed.
|
if (cfg != region.region->config()) {
|
||||||
if (print_region_ref_cnt(*region.region) == 0) {
|
// Region configuration changed.
|
||||||
// Region is referenced for the first time. Just change its parameters.
|
if (print_region_ref_cnt(*region.region) == 0) {
|
||||||
// Stop the background process before assigning new configuration to the regions.
|
// Region is referenced for the first time. Just change its parameters.
|
||||||
t_config_option_keys diff = region.region->config().diff(cfg);
|
// Stop the background process before assigning new configuration to the regions.
|
||||||
callback_invalidate(region.region->config(), cfg, diff);
|
t_config_option_keys diff = region.region->config().diff(cfg);
|
||||||
region.region->config_apply_only(cfg, diff, false);
|
callback_invalidate(region.region->config(), cfg, diff);
|
||||||
} else {
|
region.region->config_apply_only(cfg, diff, false);
|
||||||
// Region is referenced multiple times, thus the region is being split. We need to reslice.
|
} else {
|
||||||
return false;
|
// Region is referenced multiple times, thus the region is being split. We need to reslice.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
print_region_ref_inc(*region.region);
|
||||||
}
|
}
|
||||||
print_region_ref_inc(*region.region);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify and / or update PrintRegions produced by color painting.
|
// Verify and / or update PrintRegions produced by color painting.
|
||||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges) {
|
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges) {
|
||||||
|
@ -707,9 +708,9 @@ void update_volume_bboxes(
|
||||||
std::vector<PrintObjectRegions::VolumeExtents> volumes_old(std::move(layer_range.volumes));
|
std::vector<PrintObjectRegions::VolumeExtents> volumes_old(std::move(layer_range.volumes));
|
||||||
layer_range.volumes.reserve(model_volumes.size());
|
layer_range.volumes.reserve(model_volumes.size());
|
||||||
for (const ModelVolume *model_volume : model_volumes)
|
for (const ModelVolume *model_volume : model_volumes)
|
||||||
if (model_volume_needs_bbox(*model_volume)) {
|
if (model_volume_solid_or_modifier(*model_volume)) {
|
||||||
if (std::binary_search(cached_volume_ids.begin(), cached_volume_ids.end(), model_volume->id())) {
|
if (std::binary_search(cached_volume_ids.begin(), cached_volume_ids.end(), model_volume->id())) {
|
||||||
auto it = lower_bound_by_predicate(volumes_old.begin(), volumes_old.end(), [model_volume](PrintObjectRegions::VolumeExtents &v) { return v.volume_id == model_volume->id(); });
|
auto it = lower_bound_by_predicate(volumes_old.begin(), volumes_old.end(), [model_volume](PrintObjectRegions::VolumeExtents &l) { return l.volume_id < model_volume->id(); });
|
||||||
if (it != volumes_old.end() && it->volume_id == model_volume->id())
|
if (it != volumes_old.end() && it->volume_id == model_volume->id())
|
||||||
layer_range.volumes.emplace_back(*it);
|
layer_range.volumes.emplace_back(*it);
|
||||||
} else
|
} else
|
||||||
|
@ -737,11 +738,11 @@ void update_volume_bboxes(
|
||||||
ranges.emplace_back(r);
|
ranges.emplace_back(r);
|
||||||
}
|
}
|
||||||
for (const ModelVolume *model_volume : model_volumes)
|
for (const ModelVolume *model_volume : model_volumes)
|
||||||
if (model_volume_needs_bbox(*model_volume)) {
|
if (model_volume_solid_or_modifier(*model_volume)) {
|
||||||
if (std::binary_search(cached_volume_ids.begin(), cached_volume_ids.end(), model_volume->id())) {
|
if (std::binary_search(cached_volume_ids.begin(), cached_volume_ids.end(), model_volume->id())) {
|
||||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges) {
|
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges) {
|
||||||
const auto &vold = volumes_old[&layer_range - layer_ranges.data()];
|
const auto &vold = volumes_old[&layer_range - layer_ranges.data()];
|
||||||
auto it = lower_bound_by_predicate(vold.begin(), vold.end(), [model_volume](const PrintObjectRegions::VolumeExtents &v) { return v.volume_id == model_volume->id(); });
|
auto it = lower_bound_by_predicate(vold.begin(), vold.end(), [model_volume](const PrintObjectRegions::VolumeExtents &l) { return l.volume_id < model_volume->id(); });
|
||||||
if (it != vold.end() && it->volume_id == model_volume->id())
|
if (it != vold.end() && it->volume_id == model_volume->id())
|
||||||
layer_range.volumes.emplace_back(*it);
|
layer_range.volumes.emplace_back(*it);
|
||||||
}
|
}
|
||||||
|
@ -776,20 +777,22 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||||
auto &all_regions = out->all_regions;
|
auto &all_regions = out->all_regions;
|
||||||
auto &layer_ranges_regions = out->layer_ranges;
|
auto &layer_ranges_regions = out->layer_ranges;
|
||||||
|
|
||||||
|
all_regions.clear();
|
||||||
|
|
||||||
bool reuse_old = print_object_regions_old && !print_object_regions_old->layer_ranges.empty();
|
bool reuse_old = print_object_regions_old && !print_object_regions_old->layer_ranges.empty();
|
||||||
|
|
||||||
if (reuse_old) {
|
if (reuse_old) {
|
||||||
#ifndef NDEBUG
|
// Reuse old bounding boxes of some ModelVolumes and their ranges.
|
||||||
// Verify that the old ranges match the new ranges.
|
// Verify that the old ranges match the new ranges.
|
||||||
assert(model_layer_ranges.size() == layer_ranges_regions.size());
|
assert(model_layer_ranges.size() == layer_ranges_regions.size());
|
||||||
for (const auto &range : model_layer_ranges) {
|
for (const auto &range : model_layer_ranges) {
|
||||||
const PrintObjectRegions::LayerRangeRegions &r = layer_ranges_regions[&range - &*model_layer_ranges.begin()];
|
PrintObjectRegions::LayerRangeRegions &r = layer_ranges_regions[&range - &*model_layer_ranges.begin()];
|
||||||
assert(range.layer_height_range == r.layer_height_range);
|
assert(range.layer_height_range == r.layer_height_range);
|
||||||
assert(range.config == r.config);
|
// If model::assign_copy() is called, layer_ranges_regions is copied thus the pointers to configs are lost.
|
||||||
assert(r.volume_regions.empty());
|
r.config = range.config;
|
||||||
assert(r.painted_regions.empty());
|
r.volume_regions.clear();
|
||||||
|
r.painted_regions.clear();
|
||||||
}
|
}
|
||||||
#endif // NDEBUG
|
|
||||||
} else {
|
} else {
|
||||||
out->trafo_bboxes = trafo;
|
out->trafo_bboxes = trafo;
|
||||||
layer_ranges_regions.reserve(model_layer_ranges.size());
|
layer_ranges_regions.reserve(model_layer_ranges.size());
|
||||||
|
@ -816,29 +819,34 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||||
// Chain the regions in the order they are stored in the volumes list.
|
// Chain the regions in the order they are stored in the volumes list.
|
||||||
for (int volume_id = 0; volume_id < int(model_volumes.size()); ++ volume_id) {
|
for (int volume_id = 0; volume_id < int(model_volumes.size()); ++ volume_id) {
|
||||||
const ModelVolume &volume = *model_volumes[volume_id];
|
const ModelVolume &volume = *model_volumes[volume_id];
|
||||||
if (volume.type() == ModelVolumeType::MODEL_PART || volume.type() == ModelVolumeType::PARAMETER_MODIFIER) {
|
if (model_volume_solid_or_modifier(volume)) {
|
||||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
|
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
|
||||||
if (const BoundingBoxf3 *bbox = find_volume_extents(layer_range, volume); bbox) {
|
if (const BoundingBoxf3 *bbox = find_volume_extents(layer_range, volume); bbox) {
|
||||||
if (volume.is_model_part())
|
if (volume.is_model_part()) {
|
||||||
|
// Add a model volume, assign an existing region or generate a new one.
|
||||||
layer_range.volume_regions.push_back({
|
layer_range.volume_regions.push_back({
|
||||||
&volume, -1,
|
&volume, -1,
|
||||||
get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders)),
|
get_create_region(region_config_from_model_volume(default_region_config, layer_range.config, volume, num_extruders)),
|
||||||
bbox
|
bbox
|
||||||
});
|
});
|
||||||
else {
|
} else if (volume.is_negative_volume()) {
|
||||||
|
// Add a negative (subtractor) volume. Such volume has neither region nor parent volume assigned.
|
||||||
|
layer_range.volume_regions.push_back({ &volume, -1, nullptr, bbox });
|
||||||
|
} else {
|
||||||
assert(volume.is_modifier());
|
assert(volume.is_modifier());
|
||||||
// Modifiers may be chained one over the other. Check for overlap, merge DynamicPrintConfigs.
|
// Modifiers may be chained one over the other. Check for overlap, merge DynamicPrintConfigs.
|
||||||
for (int parent_region_id = int(layer_range.volume_regions.size()) - 1; parent_region_id >= 0; -- parent_region_id) {
|
for (int parent_region_id = int(layer_range.volume_regions.size()) - 1; parent_region_id >= 0; -- parent_region_id)
|
||||||
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
if (const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||||
const BoundingBoxf3 *parent_bbox = find_volume_extents(layer_range, *parent_region.model_volume);
|
parent_region.model_volume->is_model_part() || parent_region.model_volume->is_modifier()) {
|
||||||
assert(parent_bbox != nullptr);
|
const BoundingBoxf3 *parent_bbox = find_volume_extents(layer_range, *parent_region.model_volume);
|
||||||
if (parent_bbox->overlap(*bbox))
|
assert(parent_bbox != nullptr);
|
||||||
layer_range.volume_regions.push_back( {
|
if (parent_bbox->overlap(*bbox))
|
||||||
&volume, parent_region_id,
|
layer_range.volume_regions.push_back({
|
||||||
get_create_region(region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders)),
|
&volume, parent_region_id,
|
||||||
bbox
|
get_create_region(region_config_from_model_volume(parent_region.region->config(), nullptr, volume, num_extruders)),
|
||||||
});
|
bbox
|
||||||
}
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,13 +855,14 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||||
// Finally add painting regions.
|
// Finally add painting regions.
|
||||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
|
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions)
|
||||||
for (unsigned int painted_extruder_id : painting_extruders)
|
for (unsigned int painted_extruder_id : painting_extruders)
|
||||||
for (int parent_region_id = 0; parent_region_id < int(layer_range.volume_regions.size()); ++ parent_region_id) {
|
for (int parent_region_id = 0; parent_region_id < int(layer_range.volume_regions.size()); ++ parent_region_id)
|
||||||
const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
if (const PrintObjectRegions::VolumeRegion &parent_region = layer_range.volume_regions[parent_region_id];
|
||||||
PrintRegionConfig cfg = parent_region.region->config();
|
parent_region.model_volume->is_model_part() || parent_region.model_volume->is_modifier()) {
|
||||||
cfg.perimeter_extruder.value = painted_extruder_id;
|
PrintRegionConfig cfg = parent_region.region->config();
|
||||||
cfg.infill_extruder.value = painted_extruder_id;
|
cfg.perimeter_extruder.value = painted_extruder_id;
|
||||||
layer_range.painted_regions.push_back({ painted_extruder_id, parent_region_id, get_create_region(std::move(cfg))});
|
cfg.infill_extruder.value = painted_extruder_id;
|
||||||
}
|
layer_range.painted_regions.push_back({ painted_extruder_id, parent_region_id, get_create_region(std::move(cfg))});
|
||||||
|
}
|
||||||
|
|
||||||
return out.release();
|
return out.release();
|
||||||
}
|
}
|
||||||
|
@ -1023,6 +1032,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
PrintObjectStatusDB print_object_status_db(m_objects);
|
PrintObjectStatusDB print_object_status_db(m_objects);
|
||||||
|
|
||||||
// 3) Synchronize ModelObjects & PrintObjects.
|
// 3) Synchronize ModelObjects & PrintObjects.
|
||||||
|
const std::initializer_list<ModelVolumeType> solid_or_modifier_types { ModelVolumeType::MODEL_PART, ModelVolumeType::NEGATIVE_VOLUME, ModelVolumeType::PARAMETER_MODIFIER };
|
||||||
for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
|
for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
|
||||||
ModelObject &model_object = *m_model.objects[idx_model_object];
|
ModelObject &model_object = *m_model.objects[idx_model_object];
|
||||||
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
|
ModelObjectStatus &model_object_status = const_cast<ModelObjectStatus&>(model_object_status_db.reuse(model_object));
|
||||||
|
@ -1034,27 +1044,24 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
assert(model_object_status.status == ModelObjectStatus::Old || model_object_status.status == ModelObjectStatus::Moved);
|
assert(model_object_status.status == ModelObjectStatus::Old || model_object_status.status == ModelObjectStatus::Moved);
|
||||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||||
// Only volume IDs, volume types, transformation matrices and their order are checked, configuration and other parameters are NOT checked.
|
// Only volume IDs, volume types, transformation matrices and their order are checked, configuration and other parameters are NOT checked.
|
||||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART);
|
bool solid_or_modifier_differ = model_volume_list_changed(model_object, model_object_new, solid_or_modifier_types);
|
||||||
bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::PARAMETER_MODIFIER);
|
|
||||||
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
|
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
|
||||||
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||||
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
|
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
|
||||||
|
bool model_origin_translation_differ = model_object.origin_translation != model_object_new.origin_translation;
|
||||||
auto print_objects_range = print_object_status_db.get_range(model_object);
|
auto print_objects_range = print_object_status_db.get_range(model_object);
|
||||||
assert(print_objects_range.begin() != print_objects_range.end());
|
assert(print_objects_range.begin() != print_objects_range.end());
|
||||||
// All PrintObjects in print_objects_range shall point to the same prints_objects_regions
|
// All PrintObjects in print_objects_range shall point to the same prints_objects_regions
|
||||||
model_object_status.print_object_regions = print_objects_range.begin()->print_object->m_shared_regions;
|
model_object_status.print_object_regions = print_objects_range.begin()->print_object->m_shared_regions;
|
||||||
model_object_status.print_object_regions->ref_cnt_inc();
|
model_object_status.print_object_regions->ref_cnt_inc();
|
||||||
if (model_parts_differ || modifiers_differ ||
|
if (solid_or_modifier_differ || model_origin_translation_differ || layer_height_ranges_differ ||
|
||||||
model_object.origin_translation != model_object_new.origin_translation ||
|
! model_object.layer_height_profile.timestamp_matches(model_object_new.layer_height_profile)) {
|
||||||
! model_object.layer_height_profile.timestamp_matches(model_object_new.layer_height_profile) ||
|
|
||||||
layer_height_ranges_differ) {
|
|
||||||
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
|
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
|
||||||
model_object_status.print_object_regions_status =
|
model_object_status.print_object_regions_status = model_origin_translation_differ || layer_height_ranges_differ ?
|
||||||
model_object.origin_translation == model_object_new.origin_translation && ! layer_height_ranges_differ ?
|
// Drop print_objects_regions.
|
||||||
// Drop print_objects_regions.
|
ModelObjectStatus::PrintObjectRegionsStatus::Invalid :
|
||||||
ModelObjectStatus::PrintObjectRegionsStatus::Invalid :
|
// Reuse bounding boxes of print_objects_regions for ModelVolumes with unmodified transformation.
|
||||||
// Reuse bounding boxes of print_objects_regions for ModelVolumes with unmodified transformation.
|
ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid;
|
||||||
ModelObjectStatus::PrintObjectRegionsStatus::PartiallyValid;
|
|
||||||
for (const PrintObjectStatus &print_object_status : print_objects_range) {
|
for (const PrintObjectStatus &print_object_status : print_objects_range) {
|
||||||
update_apply_status(print_object_status.print_object->invalidate_all_steps());
|
update_apply_status(print_object_status.print_object->invalidate_all_steps());
|
||||||
const_cast<PrintObjectStatus&>(print_object_status).status = PrintObjectStatus::Deleted;
|
const_cast<PrintObjectStatus&>(print_object_status).status = PrintObjectStatus::Deleted;
|
||||||
|
@ -1085,7 +1092,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! model_parts_differ && ! modifiers_differ) {
|
if (! solid_or_modifier_differ) {
|
||||||
// Synchronize Object's config.
|
// Synchronize Object's config.
|
||||||
bool object_config_changed = ! model_object.config.timestamp_matches(model_object_new.config);
|
bool object_config_changed = ! model_object.config.timestamp_matches(model_object_new.config);
|
||||||
if (object_config_changed)
|
if (object_config_changed)
|
||||||
|
|
|
@ -306,21 +306,20 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||||
float z = zs_complex[range.begin()].second;
|
float z = zs_complex[range.begin()].second;
|
||||||
auto it_layer_range = lower_bound_by_predicate(print_object_regions.layer_ranges.begin(), print_object_regions.layer_ranges.end(),
|
auto it_layer_range = lower_bound_by_predicate(print_object_regions.layer_ranges.begin(), print_object_regions.layer_ranges.end(),
|
||||||
[z](const PrintObjectRegions::LayerRangeRegions &lr){ return lr.layer_height_range.second < z; });
|
[z](const PrintObjectRegions::LayerRangeRegions &lr){ return lr.layer_height_range.second < z; });
|
||||||
assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first >= z && z <= it_layer_range->layer_height_range.second);
|
assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first <= z && z <= it_layer_range->layer_height_range.second);
|
||||||
if (z == it_layer_range->layer_height_range.second)
|
if (z == it_layer_range->layer_height_range.second)
|
||||||
if (auto it_next = it_layer_range; ++ it_next != print_object_regions.layer_ranges.end() && it_next->layer_height_range.first == z)
|
if (auto it_next = it_layer_range; ++ it_next != print_object_regions.layer_ranges.end() && it_next->layer_height_range.first == z)
|
||||||
it_layer_range = it_next;
|
it_layer_range = it_next;
|
||||||
assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first >= z && z < it_layer_range->layer_height_range.second);
|
assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first <= z && z <= it_layer_range->layer_height_range.second);
|
||||||
// Per volume_regions slices at this Z height.
|
// Per volume_regions slices at this Z height.
|
||||||
struct RegionSlice {
|
struct RegionSlice {
|
||||||
ExPolygons expolygons;
|
ExPolygons expolygons;
|
||||||
// Identifier of this region in PrintObjectRegions::all_regions
|
// Identifier of this region in PrintObjectRegions::all_regions
|
||||||
int region_id;
|
int region_id;
|
||||||
ObjectID volume_id;
|
ObjectID volume_id;
|
||||||
bool empty() const { return region_id < 0 || expolygons.empty(); }
|
|
||||||
bool operator<(const RegionSlice &rhs) const {
|
bool operator<(const RegionSlice &rhs) const {
|
||||||
bool this_empty = this->empty();
|
bool this_empty = this->region_id < 0 || this->expolygons.empty();
|
||||||
bool rhs_empty = rhs.empty();
|
bool rhs_empty = rhs.region_id < 0 || rhs.expolygons.empty();
|
||||||
// Sort the empty items to the end of the list.
|
// Sort the empty items to the end of the list.
|
||||||
// Sort by region_id & volume_id lexicographically.
|
// Sort by region_id & volume_id lexicographically.
|
||||||
return ! this_empty && (rhs_empty || (this->region_id < rhs.region_id || (this->region_id == rhs.region_id && volume_id < volume_id)));
|
return ! this_empty && (rhs_empty || (this->region_id < rhs.region_id || (this->region_id == rhs.region_id && volume_id < volume_id)));
|
||||||
|
@ -331,7 +330,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||||
auto [z_idx, z] = zs_complex[zs_complex_idx];
|
auto [z_idx, z] = zs_complex[zs_complex_idx];
|
||||||
for (; it_layer_range->layer_height_range.second <= z; ++ it_layer_range)
|
for (; it_layer_range->layer_height_range.second <= z; ++ it_layer_range)
|
||||||
assert(it_layer_range != print_object_regions.layer_ranges.end());
|
assert(it_layer_range != print_object_regions.layer_ranges.end());
|
||||||
assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first >= z && z < it_layer_range->layer_height_range.second);
|
assert(it_layer_range != print_object_regions.layer_ranges.end() && it_layer_range->layer_height_range.first <= z && z < it_layer_range->layer_height_range.second);
|
||||||
const PrintObjectRegions::LayerRangeRegions &layer_range = *it_layer_range;
|
const PrintObjectRegions::LayerRangeRegions &layer_range = *it_layer_range;
|
||||||
{
|
{
|
||||||
std::vector<VolumeSlices*> &layer_range_regions_to_slices = layer_ranges_regions_to_slices[it_layer_range - print_object_regions.layer_ranges.begin()];
|
std::vector<VolumeSlices*> &layer_range_regions_to_slices = layer_ranges_regions_to_slices[it_layer_range - print_object_regions.layer_ranges.begin()];
|
||||||
|
@ -344,26 +343,27 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int idx_region = 0; idx_region < int(layer_range.volume_regions.size()); ++ idx_region)
|
for (int idx_region = 0; idx_region < int(layer_range.volume_regions.size()); ++ idx_region)
|
||||||
if (! temp_slices[idx_region].empty()) {
|
if (! temp_slices[idx_region].expolygons.empty()) {
|
||||||
const PrintObjectRegions::VolumeRegion ®ion = layer_range.volume_regions[idx_region];
|
const PrintObjectRegions::VolumeRegion ®ion = layer_range.volume_regions[idx_region];
|
||||||
if (region.model_volume->is_modifier()) {
|
if (region.model_volume->is_modifier()) {
|
||||||
assert(region.parent > -1);
|
assert(region.parent > -1);
|
||||||
bool next_region_same_modifier = idx_region + 1 < int(temp_slices.size()) && layer_range.volume_regions[idx_region + 1].model_volume == region.model_volume;
|
bool next_region_same_modifier = idx_region + 1 < int(temp_slices.size()) && layer_range.volume_regions[idx_region + 1].model_volume == region.model_volume;
|
||||||
if (next_region_same_modifier)
|
|
||||||
temp_slices[idx_region + 1] = std::move(temp_slices[idx_region]);
|
|
||||||
RegionSlice &parent_slice = temp_slices[region.parent];
|
RegionSlice &parent_slice = temp_slices[region.parent];
|
||||||
RegionSlice &this_slice = temp_slices[idx_region];
|
RegionSlice &this_slice = temp_slices[idx_region];
|
||||||
if (parent_slice.empty())
|
ExPolygons source = std::move(this_slice.expolygons);
|
||||||
this_slice.expolygons.clear();
|
if (parent_slice.expolygons.empty()) {
|
||||||
else {
|
this_slice .expolygons.clear();
|
||||||
RegionSlice &source_slice = temp_slices[idx_region + int(next_region_same_modifier)];
|
} else {
|
||||||
this_slice .expolygons = intersection_ex(parent_slice.expolygons, source_slice.expolygons);
|
this_slice .expolygons = intersection_ex(parent_slice.expolygons, source);
|
||||||
parent_slice.expolygons = diff_ex (parent_slice.expolygons, source_slice.expolygons);
|
parent_slice.expolygons = diff_ex (parent_slice.expolygons, source);
|
||||||
}
|
}
|
||||||
|
if (next_region_same_modifier)
|
||||||
|
// To be used in the following iteration.
|
||||||
|
temp_slices[idx_region + 1].expolygons = std::move(source);
|
||||||
} else if ((region.model_volume->is_model_part() && clip_multipart_objects) || region.model_volume->is_negative_volume()) {
|
} else if ((region.model_volume->is_model_part() && clip_multipart_objects) || region.model_volume->is_negative_volume()) {
|
||||||
// Clip every non-zero region preceding it.
|
// Clip every non-zero region preceding it.
|
||||||
for (int idx_region2 = 0; idx_region2 < idx_region; ++ idx_region2)
|
for (int idx_region2 = 0; idx_region2 < idx_region; ++ idx_region2)
|
||||||
if (! temp_slices[idx_region2].empty()) {
|
if (! temp_slices[idx_region2].expolygons.empty()) {
|
||||||
if (const PrintObjectRegions::VolumeRegion ®ion2 = layer_range.volume_regions[idx_region2];
|
if (const PrintObjectRegions::VolumeRegion ®ion2 = layer_range.volume_regions[idx_region2];
|
||||||
! region2.model_volume->is_negative_volume() && overlap_in_xy(*region.bbox, *region2.bbox))
|
! region2.model_volume->is_negative_volume() && overlap_in_xy(*region.bbox, *region2.bbox))
|
||||||
temp_slices[idx_region2].expolygons = diff_ex(temp_slices[idx_region2].expolygons, temp_slices[idx_region].expolygons);
|
temp_slices[idx_region2].expolygons = diff_ex(temp_slices[idx_region2].expolygons, temp_slices[idx_region].expolygons);
|
||||||
|
@ -373,7 +373,7 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||||
// Sort by region_id, push empty slices to the end.
|
// Sort by region_id, push empty slices to the end.
|
||||||
std::sort(temp_slices.begin(), temp_slices.end());
|
std::sort(temp_slices.begin(), temp_slices.end());
|
||||||
// Remove the empty slices.
|
// Remove the empty slices.
|
||||||
temp_slices.erase(std::find_if(temp_slices.begin(), temp_slices.end(), [](const auto &slice) { return slice.empty(); }), temp_slices.end());
|
temp_slices.erase(std::find_if(temp_slices.begin(), temp_slices.end(), [](const auto &slice) { return slice.region_id == -1 || slice.expolygons.empty(); }), temp_slices.end());
|
||||||
// Merge slices and store them to the output.
|
// Merge slices and store them to the output.
|
||||||
for (int i = 0; i < int(temp_slices.size());) {
|
for (int i = 0; i < int(temp_slices.size());) {
|
||||||
// Find a range of temp_slices with the same region_id.
|
// Find a range of temp_slices with the same region_id.
|
||||||
|
|
|
@ -151,7 +151,7 @@ wxBitmap SettingsFactory::get_category_bitmap(const std::string& category_name)
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
// Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important
|
// Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important
|
||||||
std::vector<std::pair<std::string, std::string>> MenuFactory::ADD_VOLUME_MENU_ITEMS = {
|
const std::vector<std::pair<std::string, std::string>> MenuFactory::ADD_VOLUME_MENU_ITEMS {
|
||||||
// menu_item Name menu_item bitmap name
|
// menu_item Name menu_item bitmap name
|
||||||
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
|
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
|
||||||
{L("Add negative volume"), "add_negative" }, // ~ModelVolumeType::NEGATIVE_VOLUME
|
{L("Add negative volume"), "add_negative" }, // ~ModelVolumeType::NEGATIVE_VOLUME
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct SettingsFactory
|
||||||
class MenuFactory
|
class MenuFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS;
|
static const std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS;
|
||||||
static std::vector<wxBitmap> get_volume_bitmaps();
|
static std::vector<wxBitmap> get_volume_bitmaps();
|
||||||
|
|
||||||
MenuFactory();
|
MenuFactory();
|
||||||
|
|
Loading…
Add table
Reference in a new issue