Refactored PrintObject::m_region_volumes for extensibility.

WIP for multi-material painting.
This commit is contained in:
Vojtech Bubnik 2021-05-06 15:48:38 +02:00
parent dd72016159
commit feefbc575a
3 changed files with 67 additions and 44 deletions

View file

@ -152,6 +152,34 @@ struct PrintInstance
typedef std::vector<PrintInstance> PrintInstances; typedef std::vector<PrintInstance> PrintInstances;
// Region and its volumes (printing volumes or modifier volumes)
struct PrintRegionVolumes
{
// Single volume + Z range assigned to a region.
struct VolumeWithZRange {
// Z range to slice this ModelVolume over.
t_layer_height_range layer_height_range;
// Index of a ModelVolume inside its parent ModelObject.
int volume_idx;
};
// Overriding one region with some other extruder, producing another region.
// The region is owned by PrintObject::m_all_regions.
struct ExtruderOverride {
unsigned int extruder;
// const PrintRegion *region;
};
// The region is owned by PrintObject::m_all_regions.
// const PrintRegion *region;
// Possible overrides of the default region extruder.
std::vector<ExtruderOverride> overrides;
// List of ModelVolume indices and layer ranges of thereof.
std::vector<VolumeWithZRange> volumes;
// Is this region printing in any layer?
// bool printing { false };
};
class PrintObject : public PrintObjectBaseWithState<Print, PrintObjectStep, posCount> class PrintObject : public PrintObjectBaseWithState<Print, PrintObjectStep, posCount>
{ {
private: // Prevents erroneous use by other classes. private: // Prevents erroneous use by other classes.
@ -186,7 +214,7 @@ public:
void add_region_volume(unsigned int region_id, int volume_id, const t_layer_height_range &layer_range) { void add_region_volume(unsigned int region_id, int volume_id, const t_layer_height_range &layer_range) {
if (region_id >= m_region_volumes.size()) if (region_id >= m_region_volumes.size())
m_region_volumes.resize(region_id + 1); m_region_volumes.resize(region_id + 1);
m_region_volumes[region_id].emplace_back(layer_range, volume_id); m_region_volumes[region_id].volumes.push_back({ layer_range, 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
@ -307,7 +335,7 @@ private:
std::vector<std::unique_ptr<PrintRegion>> m_all_regions; std::vector<std::unique_ptr<PrintRegion>> m_all_regions;
// vector of (layer height ranges and vectors of volume ids), indexed by region_id // vector of (layer height ranges and vectors of volume ids), indexed by region_id
std::vector<std::vector<std::pair<t_layer_height_range, int>>> m_region_volumes; std::vector<PrintRegionVolumes> m_region_volumes;
SlicingParameters m_slicing_params; SlicingParameters m_slicing_params;
LayerPtrs m_layers; LayerPtrs m_layers;
@ -513,15 +541,11 @@ public:
std::string output_filename(const std::string &filename_base = std::string()) const override; std::string output_filename(const std::string &filename_base = std::string()) const override;
// Accessed by SupportMaterial
size_t num_print_regions() const throw() { return m_print_regions.size(); } size_t num_print_regions() const throw() { return m_print_regions.size(); }
const PrintRegion& get_print_region(size_t idx) const { return *m_print_regions[idx]; } const PrintRegion& get_print_region(size_t idx) const { return *m_print_regions[idx]; }
const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; } // #ys_FIXME just for testing const ToolOrdering& get_tool_ordering() const { return m_wipe_tower_data.tool_ordering; }
protected: protected:
// methods for handling regions
PrintRegion& get_print_region(size_t idx) { return *m_print_regions[idx]; }
// Invalidates the step, and its depending steps in Print. // Invalidates the step, and its depending steps in Print.
bool invalidate_step(PrintStep step); bool invalidate_step(PrintStep step);

View file

@ -694,9 +694,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
PrintRegion &region = *print_object->m_all_regions[region_id]; PrintRegion &region = *print_object->m_all_regions[region_id];
PrintRegionConfig region_config; PrintRegionConfig region_config;
bool region_config_set = false; bool region_config_set = false;
for (const std::pair<t_layer_height_range, int> &volume_and_range : print_object->m_region_volumes[region_id]) { for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : print_object->m_region_volumes[region_id].volumes) {
const ModelVolume &volume = *print_object->model_object()->volumes[volume_and_range.second]; const ModelVolume &volume = *print_object->model_object()->volumes[volume_w_zrange.volume_idx];
const DynamicPrintConfig *layer_range_config = layer_ranges->config(volume_and_range.first); const DynamicPrintConfig *layer_range_config = layer_ranges->config(volume_w_zrange.layer_height_range);
PrintRegionConfig this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, layer_range_config, volume, num_extruders); PrintRegionConfig this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, layer_range_config, volume, num_extruders);
if (region_config_set) { if (region_config_set) {
if (this_region_config != region_config) { if (this_region_config != region_config) {

View file

@ -1757,14 +1757,13 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
size_t num_modifiers = 0; size_t num_modifiers = 0;
for (int region_id = 0; region_id < int(m_region_volumes.size()); ++ region_id) { for (int region_id = 0; region_id < int(m_region_volumes.size()); ++ region_id) {
int last_volume_id = -1; int last_volume_id = -1;
for (const std::pair<t_layer_height_range, int> &volume_and_range : m_region_volumes[region_id]) { for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : m_region_volumes[region_id].volumes) {
const int volume_id = volume_and_range.second; const ModelVolume *model_volume = this->model_object()->volumes[volume_w_zrange.volume_idx];
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
if (model_volume->is_model_part()) { if (model_volume->is_model_part()) {
if (last_volume_id == volume_id) { if (last_volume_id == volume_w_zrange.volume_idx) {
has_z_ranges = true; has_z_ranges = true;
} else { } else {
last_volume_id = volume_id; last_volume_id = volume_w_zrange.volume_idx;
if (all_volumes_single_region == -2) if (all_volumes_single_region == -2)
// first model volume met // first model volume met
all_volumes_single_region = region_id; all_volumes_single_region = region_id;
@ -1821,21 +1820,21 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
std::vector<SlicedVolume> sliced_volumes; std::vector<SlicedVolume> sliced_volumes;
sliced_volumes.reserve(num_volumes); sliced_volumes.reserve(num_volumes);
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) { for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) {
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = m_region_volumes[region_id]; const PrintRegionVolumes &volumes_and_ranges = m_region_volumes[region_id];
for (size_t i = 0; i < volumes_and_ranges.size(); ) { for (size_t i = 0; i < volumes_and_ranges.volumes.size(); ) {
int volume_id = volumes_and_ranges[i].second; int volume_id = volumes_and_ranges.volumes[i].volume_idx;
const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
if (model_volume->is_model_part()) { if (model_volume->is_model_part()) {
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id; BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id;
// Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume. // Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
std::vector<t_layer_height_range> ranges; std::vector<t_layer_height_range> ranges;
ranges.emplace_back(volumes_and_ranges[i].first); ranges.emplace_back(volumes_and_ranges.volumes[i].layer_height_range);
size_t j = i + 1; size_t j = i + 1;
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) for (; j < volumes_and_ranges.volumes.size() && volume_id == volumes_and_ranges.volumes[j].volume_idx; ++ j)
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON) if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges.volumes[j].layer_height_range.first) < EPSILON)
ranges.back().second = volumes_and_ranges[j].first.second; ranges.back().second = volumes_and_ranges.volumes[j].layer_height_range.second;
else else
ranges.emplace_back(volumes_and_ranges[j].first); ranges.emplace_back(volumes_and_ranges.volumes[j].layer_height_range);
// slicing in parallel // slicing in parallel
sliced_volumes.emplace_back(volume_id, (int)region_id, this->slice_volume(slice_zs, ranges, slicing_mode, *model_volume)); sliced_volumes.emplace_back(volume_id, (int)region_id, this->slice_volume(slice_zs, ranges, slicing_mode, *model_volume));
i = j; i = j;
@ -2048,8 +2047,8 @@ std::vector<ExPolygons> PrintObject::slice_region(size_t region_id, const std::v
{ {
std::vector<const ModelVolume*> volumes; std::vector<const ModelVolume*> volumes;
if (region_id < m_region_volumes.size()) { if (region_id < m_region_volumes.size()) {
for (const std::pair<t_layer_height_range, int> &volume_and_range : m_region_volumes[region_id]) { for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : m_region_volumes[region_id].volumes) {
const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second]; const ModelVolume *volume = this->model_object()->volumes[volume_w_zrange.volume_idx];
if (volume->is_model_part()) if (volume->is_model_part())
volumes.emplace_back(volume); volumes.emplace_back(volume);
} }
@ -2057,27 +2056,27 @@ std::vector<ExPolygons> PrintObject::slice_region(size_t region_id, const std::v
return this->slice_volumes(z, mode, slicing_mode_normal_below_layer, mode_below, volumes); return this->slice_volumes(z, mode, slicing_mode_normal_below_layer, mode_below, volumes);
} }
// Z ranges are not applicable to modifier meshes, therefore a single volume will be found in volume_and_range at most once. // Z ranges are not applicable to modifier meshes, therefore a single volume will be found in volume_w_zrange at most once.
std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std::vector<float> &slice_zs) const std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std::vector<float> &slice_zs) const
{ {
std::vector<ExPolygons> out; std::vector<ExPolygons> out;
if (region_id < m_region_volumes.size()) if (region_id < m_region_volumes.size())
{ {
std::vector<std::vector<t_layer_height_range>> volume_ranges; std::vector<std::vector<t_layer_height_range>> volume_ranges;
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = m_region_volumes[region_id]; const PrintRegionVolumes &volumes_and_ranges = m_region_volumes[region_id];
volume_ranges.reserve(volumes_and_ranges.size()); volume_ranges.reserve(volumes_and_ranges.volumes.size());
for (size_t i = 0; i < volumes_and_ranges.size(); ) { for (size_t i = 0; i < volumes_and_ranges.volumes.size(); ) {
int volume_id = volumes_and_ranges[i].second; int volume_id = volumes_and_ranges.volumes[i].volume_idx;
const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
if (model_volume->is_modifier()) { if (model_volume->is_modifier()) {
std::vector<t_layer_height_range> ranges; std::vector<t_layer_height_range> ranges;
ranges.emplace_back(volumes_and_ranges[i].first); ranges.emplace_back(volumes_and_ranges.volumes[i].layer_height_range);
size_t j = i + 1; size_t j = i + 1;
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) { for (; j < volumes_and_ranges.volumes.size() && volume_id == volumes_and_ranges.volumes[j].volume_idx; ++ j) {
if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges[j].first.first) < EPSILON) if (! ranges.empty() && std::abs(ranges.back().second - volumes_and_ranges.volumes[j].layer_height_range.first) < EPSILON)
ranges.back().second = volumes_and_ranges[j].first.second; ranges.back().second = volumes_and_ranges.volumes[j].layer_height_range.second;
else else
ranges.emplace_back(volumes_and_ranges[j].first); ranges.emplace_back(volumes_and_ranges.volumes[j].layer_height_range);
} }
volume_ranges.emplace_back(std::move(ranges)); volume_ranges.emplace_back(std::move(ranges));
i = j; i = j;
@ -2099,8 +2098,8 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
if (equal_ranges && volume_ranges.front().size() == 1 && volume_ranges.front().front() == t_layer_height_range(0, DBL_MAX)) { if (equal_ranges && volume_ranges.front().size() == 1 && volume_ranges.front().front() == t_layer_height_range(0, DBL_MAX)) {
// No modifier in this region was split to layer spans. // No modifier in this region was split to layer spans.
std::vector<const ModelVolume*> volumes; std::vector<const ModelVolume*> volumes;
for (const std::pair<t_layer_height_range, int> &volume_and_range : m_region_volumes[region_id]) { for (const PrintRegionVolumes::VolumeWithZRange &volume_w_zrange : m_region_volumes[region_id].volumes) {
const ModelVolume *volume = this->model_object()->volumes[volume_and_range.second]; const ModelVolume *volume = this->model_object()->volumes[volume_w_zrange.volume_idx];
if (volume->is_modifier()) if (volume->is_modifier())
volumes.emplace_back(volume); volumes.emplace_back(volume);
} }
@ -2109,18 +2108,18 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
// Some modifier in this region was split to layer spans. // Some modifier in this region was split to layer spans.
std::vector<char> merge; std::vector<char> merge;
for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) { for (size_t region_id = 0; region_id < m_region_volumes.size(); ++ region_id) {
const std::vector<std::pair<t_layer_height_range, int>> &volumes_and_ranges = m_region_volumes[region_id]; const PrintRegionVolumes &volumes_and_ranges = m_region_volumes[region_id];
for (size_t i = 0; i < volumes_and_ranges.size(); ) { for (size_t i = 0; i < volumes_and_ranges.volumes.size(); ) {
int volume_id = volumes_and_ranges[i].second; int volume_id = volumes_and_ranges.volumes[i].volume_idx;
const ModelVolume *model_volume = this->model_object()->volumes[volume_id]; const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
if (model_volume->is_modifier()) { if (model_volume->is_modifier()) {
BOOST_LOG_TRIVIAL(debug) << "Slicing modifiers - volume " << volume_id; BOOST_LOG_TRIVIAL(debug) << "Slicing modifiers - volume " << volume_id;
// Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume. // Find the ranges of this volume. Ranges in volumes_and_ranges must not overlap for a single volume.
std::vector<t_layer_height_range> ranges; std::vector<t_layer_height_range> ranges;
ranges.emplace_back(volumes_and_ranges[i].first); ranges.emplace_back(volumes_and_ranges.volumes[i].layer_height_range);
size_t j = i + 1; size_t j = i + 1;
for (; j < volumes_and_ranges.size() && volume_id == volumes_and_ranges[j].second; ++ j) for (; j < volumes_and_ranges.volumes.size() && volume_id == volumes_and_ranges.volumes[j].volume_idx; ++ j)
ranges.emplace_back(volumes_and_ranges[j].first); ranges.emplace_back(volumes_and_ranges.volumes[j].layer_height_range);
// slicing in parallel // slicing in parallel
std::vector<ExPolygons> this_slices = this->slice_volume(slice_zs, ranges, SlicingMode::Regular, *model_volume); std::vector<ExPolygons> this_slices = this->slice_volume(slice_zs, ranges, SlicingMode::Regular, *model_volume);
// Variable this_slices could be empty if no value of slice_zs is within any of the ranges of this volume. // Variable this_slices could be empty if no value of slice_zs is within any of the ranges of this volume.