Fix an "External Perimeter First" that extrude each perimeter in double if only one of the two selected.

supermerill/SuperSlicer#2267
This commit is contained in:
remi durand 2022-01-26 16:28:59 +01:00 committed by supermerill
parent ec2d3e96e7
commit 2df72fd324
21 changed files with 253 additions and 249 deletions

View File

@ -55,9 +55,11 @@ double ExtrusionPath::length() const
void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
{ {
ExtrusionEntitiesPtr to_add;
for (const Polyline &polyline : polylines) for (const Polyline &polyline : polylines)
collection->entities.emplace_back(new ExtrusionPath(polyline, *this)); to_add.emplace_back(new ExtrusionPath(polyline, *this));
} collection->append(std::move(to_add));
}
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{ {
@ -376,9 +378,9 @@ void ExtrusionPrinter::use(const ExtrusionLoop &loop) {
} }
void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) { void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) {
ss << "ExtrusionEntityCollection:" << (uint16_t)collection.role() << "{"; ss << "ExtrusionEntityCollection:" << (uint16_t)collection.role() << "{";
for (int i = 0; i < collection.entities.size(); i++) { for (int i = 0; i < collection.entities().size(); i++) {
if (i != 0) ss << ","; if (i != 0) ss << ",";
collection.entities[i]->visit(*this); collection.entities()[i]->visit(*this);
} }
if(!collection.can_sort()) ss<<", no_sort=true"; if(!collection.can_sort()) ss<<", no_sort=true";
ss << "}"; ss << "}";
@ -387,8 +389,8 @@ void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) {
void ExtrusionLength::default_use(const ExtrusionEntity& entity) { dist += entity.length(); }; void ExtrusionLength::default_use(const ExtrusionEntity& entity) { dist += entity.length(); };
void ExtrusionLength::use(const ExtrusionEntityCollection& collection) { void ExtrusionLength::use(const ExtrusionEntityCollection& collection) {
for (int i = 0; i < collection.entities.size(); i++) { for (int i = 0; i < collection.entities().size(); i++) {
collection.entities[i]->visit(*this); collection.entities()[i]->visit(*this);
} }
} }
@ -409,7 +411,7 @@ void ExtrusionVisitorRecursiveConst::use(const ExtrusionLoop& loop) {
} }
} }
void ExtrusionVisitorRecursiveConst::use(const ExtrusionEntityCollection& collection) { void ExtrusionVisitorRecursiveConst::use(const ExtrusionEntityCollection& collection) {
for (const ExtrusionEntity* entity : collection.entities) { for (const ExtrusionEntity* entity : collection.entities()) {
entity->visit(*this); entity->visit(*this);
} }
} }

View File

@ -28,27 +28,27 @@ ExtrusionEntityCollection& ExtrusionEntityCollection::operator= (const Extrusion
{ {
this->no_sort = other.no_sort; this->no_sort = other.no_sort;
clear(); clear();
this->append(other.entities); this->append(other.m_entities);
return *this; return *this;
} }
void ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c) void ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c)
{ {
std::swap(this->entities, c.entities); std::swap(this->m_entities, c.m_entities);
std::swap(this->no_sort, c.no_sort); std::swap(this->no_sort, c.no_sort);
} }
void ExtrusionEntityCollection::clear() void ExtrusionEntityCollection::clear()
{ {
for (size_t i = 0; i < this->entities.size(); ++i) for (size_t i = 0; i < this->m_entities.size(); ++i)
delete this->entities[i]; delete this->m_entities[i];
this->entities.clear(); this->m_entities.clear();
} }
ExtrusionEntityCollection::operator ExtrusionPaths() const ExtrusionEntityCollection::operator ExtrusionPaths() const
{ {
ExtrusionPaths paths; ExtrusionPaths paths;
for (const ExtrusionEntity *ptr : this->entities) { for (const ExtrusionEntity *ptr : this->entities()) {
if (const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ptr)) if (const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ptr))
paths.push_back(*path); paths.push_back(*path);
} }
@ -57,26 +57,26 @@ ExtrusionEntityCollection::operator ExtrusionPaths() const
void ExtrusionEntityCollection::reverse() void ExtrusionEntityCollection::reverse()
{ {
for (ExtrusionEntity *ptr : this->entities) for (ExtrusionEntity *ptr : this->m_entities)
{ {
// Don't reverse it if it's a loop, as it doesn't change anything in terms of elements ordering // Don't reverse it if it's a loop, as it doesn't change anything in terms of elements ordering
// and caller might rely on winding order // and caller might rely on winding order
if (ptr->can_reverse() && !ptr->is_loop()) if (ptr->can_reverse() && !ptr->is_loop())
ptr->reverse(); ptr->reverse();
} }
std::reverse(this->entities.begin(), this->entities.end()); std::reverse(this->m_entities.begin(), this->m_entities.end());
} }
void ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity) void ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity)
{ {
delete this->entities[i]; delete this->m_entities[i];
this->entities[i] = entity.clone(); this->m_entities[i] = entity.clone();
} }
void ExtrusionEntityCollection::remove(size_t i) void ExtrusionEntityCollection::remove(size_t i)
{ {
delete this->entities[i]; delete this->m_entities[i];
this->entities.erase(this->entities.begin() + i); this->m_entities.erase(this->m_entities.begin() + i);
} }
ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const ExtrusionEntitiesPtr& extrusion_entities, const Point &start_near, ExtrusionRole role) ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const ExtrusionEntitiesPtr& extrusion_entities, const Point &start_near, ExtrusionRole role)
@ -89,7 +89,7 @@ ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const Ext
// if (role == erMixed) // if (role == erMixed)
// out = *this; // out = *this;
// else { // else {
// for (const ExtrusionEntity *ee : this->entities) { // for (const ExtrusionEntity *ee : this->entities()) {
// if (role != erMixed) { // if (role != erMixed) {
// // The caller wants only paths with a specific extrusion role. // // The caller wants only paths with a specific extrusion role.
// auto role2 = ee->role(); // auto role2 = ee->role();
@ -99,31 +99,31 @@ ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const Ext
// continue; // continue;
// } // }
// } // }
// out.entities.emplace_back(ee->clone()); // out.entities().emplace_back(ee->clone());
// } // }
// } // }
// chain_and_reorder_extrusion_entities(out.entities, &start_near); // chain_and_reorder_extrusion_entities(out.entities(), &start_near);
//} //}
//return out; //return out;
// Return a filtered copy of the collection. // Return a filtered copy of the collection.
ExtrusionEntityCollection out; ExtrusionEntityCollection out;
out.entities = filter_by_extrusion_role(extrusion_entities, role); out.m_entities = filter_by_extrusion_role(extrusion_entities, role);
// Clone the extrusion entities. // Clone the extrusion entities.
for (ExtrusionEntity* &ptr : out.entities) for (ExtrusionEntity* &ptr : out.m_entities)
ptr = ptr->clone(); ptr = ptr->clone();
chain_and_reorder_extrusion_entities(out.entities, &start_near); chain_and_reorder_extrusion_entities(out.m_entities, &start_near);
return out; return out;
} }
void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{ {
for (const ExtrusionEntity *entity : this->entities) for (const ExtrusionEntity *entity : this->entities())
entity->polygons_covered_by_width(out, scaled_epsilon); entity->polygons_covered_by_width(out, scaled_epsilon);
} }
void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const
{ {
for (const ExtrusionEntity *entity : this->entities) for (const ExtrusionEntity *entity : this->entities())
entity->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon); entity->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon);
} }
@ -135,7 +135,7 @@ size_t ExtrusionEntityCollection::items_count() const
void void
CountEntities::use(const ExtrusionEntityCollection &coll) { CountEntities::use(const ExtrusionEntityCollection &coll) {
for (const ExtrusionEntity* entity : coll.entities) { for (const ExtrusionEntity* entity : coll.entities()) {
entity->visit(*this); entity->visit(*this);
} }
} }
@ -153,12 +153,12 @@ void
FlatenEntities::use(const ExtrusionEntityCollection &coll) { FlatenEntities::use(const ExtrusionEntityCollection &coll) {
if ((!coll.can_sort() || !this->to_fill.can_sort()) && preserve_ordering) { if ((!coll.can_sort() || !this->to_fill.can_sort()) && preserve_ordering) {
FlatenEntities unsortable(coll, preserve_ordering); FlatenEntities unsortable(coll, preserve_ordering);
for (const ExtrusionEntity* entity : coll.entities) { for (const ExtrusionEntity* entity : coll.entities()) {
entity->visit(unsortable); entity->visit(unsortable);
} }
to_fill.append(std::move(unsortable.to_fill)); to_fill.append(std::move(unsortable.to_fill));
} else { } else {
for (const ExtrusionEntity* entity : coll.entities) { for (const ExtrusionEntity* entity : coll.entities()) {
entity->visit(*this); entity->visit(*this);
} }
} }

View File

@ -29,6 +29,7 @@ private:
bool no_sort; bool no_sort;
// even if no_sort, allow to reverse() us (and our entities if they allow it, but they should) // even if no_sort, allow to reverse() us (and our entities if they allow it, but they should)
bool no_reverse; bool no_reverse;
ExtrusionEntitiesPtr m_entities; // we own these entities
public: public:
virtual ExtrusionEntityCollection* clone() const override { return new ExtrusionEntityCollection(*this); } virtual ExtrusionEntityCollection* clone() const override { return new ExtrusionEntityCollection(*this); }
// Create a new object, initialize it with this object using the move semantics. // Create a new object, initialize it with this object using the move semantics.
@ -37,14 +38,15 @@ public:
/// Owned ExtrusionEntities and descendent ExtrusionEntityCollections. /// Owned ExtrusionEntities and descendent ExtrusionEntityCollections.
/// Iterating over this needs to check each child to see if it, too is a collection. /// Iterating over this needs to check each child to see if it, too is a collection.
ExtrusionEntitiesPtr entities; // we own these entities const ExtrusionEntitiesPtr& entities() const { return m_entities; }
ExtrusionEntitiesPtr& set_entities() { return m_entities; }
ExtrusionEntityCollection(): no_sort(false), no_reverse(false) {} ExtrusionEntityCollection(): no_sort(false), no_reverse(false) {}
ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), no_reverse(other.no_reverse) { this->append(other.entities); } ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), no_reverse(other.no_reverse) { this->append(other.entities()); }
ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort), no_reverse(other.no_reverse) {} ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : m_entities(std::move(other.m_entities)), no_sort(other.no_sort), no_reverse(other.no_reverse) {}
explicit ExtrusionEntityCollection(const ExtrusionPaths &paths); explicit ExtrusionEntityCollection(const ExtrusionPaths &paths);
ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other); ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other);
ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other) ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other)
{ this->entities = std::move(other.entities); this->no_sort = other.no_sort; this->no_reverse = other.no_reverse; return *this; } { this->m_entities = std::move(other.m_entities); this->no_sort = other.no_sort; this->no_reverse = other.no_reverse; return *this; }
~ExtrusionEntityCollection() { clear(); } ~ExtrusionEntityCollection() { clear(); }
/// Operator to convert and flatten this collection to a single vector of ExtrusionPaths. /// Operator to convert and flatten this collection to a single vector of ExtrusionPaths.
@ -53,7 +55,7 @@ public:
bool is_collection() const override { return true; } bool is_collection() const override { return true; }
ExtrusionRole role() const override { ExtrusionRole role() const override {
ExtrusionRole out = erNone; ExtrusionRole out = erNone;
for (const ExtrusionEntity *ee : entities) { for (const ExtrusionEntity *ee : m_entities) {
ExtrusionRole er = ee->role(); ExtrusionRole er = ee->role();
out = (out == erNone || out == er) ? er : erMixed; out = (out == erNone || out == er) ? er : erMixed;
} }
@ -62,33 +64,33 @@ public:
void set_can_sort_reverse(bool sort, bool reverse) { this->no_sort = !sort; this->no_reverse = !reverse; } void set_can_sort_reverse(bool sort, bool reverse) { this->no_sort = !sort; this->no_reverse = !reverse; }
bool can_sort() const { return !this->no_sort; } bool can_sort() const { return !this->no_sort; }
bool can_reverse() const override { return can_sort() || !this->no_reverse; } bool can_reverse() const override { return can_sort() || !this->no_reverse; }
bool empty() const { return this->entities.empty(); } bool empty() const { return this->m_entities.empty(); }
void clear(); void clear();
void swap (ExtrusionEntityCollection &c); void swap (ExtrusionEntityCollection &c);
void append(const ExtrusionEntity &entity) { this->entities.emplace_back(entity.clone()); } void append(const ExtrusionEntity &entity) { this->m_entities.emplace_back(entity.clone()); }
void append(ExtrusionEntity &&entity) { this->entities.emplace_back(entity.clone_move()); } void append(ExtrusionEntity &&entity) { this->m_entities.emplace_back(entity.clone_move()); }
void append(const ExtrusionEntitiesPtr &entities) { void append(const ExtrusionEntitiesPtr &entities) {
this->entities.reserve(this->entities.size() + entities.size()); this->m_entities.reserve(this->m_entities.size() + entities.size());
for (const ExtrusionEntity *ptr : entities) for (const ExtrusionEntity *ptr : entities)
this->entities.emplace_back(ptr->clone()); this->m_entities.emplace_back(ptr->clone());
} }
void append(ExtrusionEntitiesPtr &&src) { void append(ExtrusionEntitiesPtr &&src) {
if (entities.empty()) if (m_entities.empty())
entities = std::move(src); m_entities = std::move(src);
else { else {
std::move(std::begin(src), std::end(src), std::back_inserter(entities)); std::move(std::begin(src), std::end(src), std::back_inserter(m_entities));
src.clear(); src.clear();
} }
} }
void append(const ExtrusionPaths &paths) { void append(const ExtrusionPaths &paths) {
this->entities.reserve(this->entities.size() + paths.size()); this->m_entities.reserve(this->m_entities.size() + paths.size());
for (const ExtrusionPath &path : paths) for (const ExtrusionPath &path : paths)
this->entities.emplace_back(path.clone()); this->m_entities.emplace_back(path.clone());
} }
void append(ExtrusionPaths &&paths) { void append(ExtrusionPaths &&paths) {
this->entities.reserve(this->entities.size() + paths.size()); this->m_entities.reserve(this->m_entities.size() + paths.size());
for (ExtrusionPath &path : paths) for (ExtrusionPath &path : paths)
this->entities.emplace_back(new ExtrusionPath(std::move(path))); this->m_entities.emplace_back(new ExtrusionPath(std::move(path)));
} }
void replace(size_t i, const ExtrusionEntity &entity); void replace(size_t i, const ExtrusionEntity &entity);
void remove(size_t i); void remove(size_t i);
@ -98,11 +100,11 @@ public:
if( this->no_sort || (role == erMixed) ) if( this->no_sort || (role == erMixed) )
return *this; return *this;
else else
return chained_path_from(this->entities, start_near, role); return chained_path_from(this->m_entities, start_near, role);
} }
void reverse() override; void reverse() override;
const Point& first_point() const override { return this->entities.front()->first_point(); } const Point& first_point() const override { return this->entities().front()->first_point(); }
const Point& last_point() const override { return this->entities.back()->last_point(); } const Point& last_point() const override { return this->entities().back()->last_point(); }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width. // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override; void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
@ -117,11 +119,11 @@ public:
/// Recursively count paths and loops contained in this collection /// Recursively count paths and loops contained in this collection
size_t items_count() const; size_t items_count() const;
/// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities vector are not collections. /// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities() vector are not collections.
/// You should be iterating over flatten().entities if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy). /// You should be iterating over flatten().entities() if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy).
/// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False). /// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False).
ExtrusionEntityCollection flatten(bool preserve_ordering = false) const; ExtrusionEntityCollection flatten(bool preserve_ordering = false) const;
double total_volume() const override { double volume=0.; for (const auto& ent : entities) volume+=ent->total_volume(); return volume; } double total_volume() const override { double volume=0.; for (const auto& ent : entities()) volume+=ent->total_volume(); return volume; }
// Following methods shall never be called on an ExtrusionEntityCollection. // Following methods shall never be called on an ExtrusionEntityCollection.
Polyline as_polyline() const override { Polyline as_polyline() const override {
@ -130,7 +132,7 @@ public:
}; };
void collect_polylines(Polylines &dst) const override { void collect_polylines(Polylines &dst) const override {
for (ExtrusionEntity* extrusion_entity : this->entities) for (const ExtrusionEntity* extrusion_entity : this->entities())
extrusion_entity->collect_polylines(dst); extrusion_entity->collect_polylines(dst);
} }

View File

@ -410,19 +410,19 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
std::vector<ExtrusionEntityCollection*> fills_by_priority; std::vector<ExtrusionEntityCollection*> fills_by_priority;
auto store_fill = [&fills_by_priority, this](size_t region_id) { auto store_fill = [&fills_by_priority, this](size_t region_id) {
if (fills_by_priority.size() == 1) { if (fills_by_priority.size() == 1) {
m_regions[region_id]->fills.append(fills_by_priority[0]->entities); m_regions[region_id]->fills.append(fills_by_priority[0]->entities());
delete fills_by_priority[0]; delete fills_by_priority[0];
} else { } else {
m_regions[region_id]->fills.set_can_sort_reverse(false, false); m_regions[region_id]->fills.set_can_sort_reverse(false, false);
ExtrusionEntityCollection* eec = new ExtrusionEntityCollection(); ExtrusionEntityCollection* eec = new ExtrusionEntityCollection();
eec->set_can_sort_reverse(false, false); eec->set_can_sort_reverse(false, false);
m_regions[region_id]->fills.entities.push_back(eec);
for (ExtrusionEntityCollection* per_priority : fills_by_priority) { for (ExtrusionEntityCollection* per_priority : fills_by_priority) {
if (!per_priority->entities.empty()) if (!per_priority->entities().empty())
eec->entities.push_back(per_priority); eec->set_entities().push_back(per_priority);
else else
delete per_priority; delete per_priority;
} }
m_regions[region_id]->fills.append(ExtrusionEntitiesPtr{ eec });
} }
fills_by_priority.clear(); fills_by_priority.clear();
}; };
@ -568,7 +568,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
//make fill //make fill
while ((size_t)surface_fill.params.priority >= fills_by_priority.size()) while ((size_t)surface_fill.params.priority >= fills_by_priority.size())
fills_by_priority.push_back(new ExtrusionEntityCollection()); fills_by_priority.push_back(new ExtrusionEntityCollection());
f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, fills_by_priority[(size_t)surface_fill.params.priority]->entities); f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, fills_by_priority[(size_t)surface_fill.params.priority]->set_entities());
} }
} }
} }
@ -580,32 +580,32 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
// The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection. // The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
// Why the paths are unpacked? // Why the paths are unpacked?
for (LayerRegion *layerm : m_regions) for (LayerRegion *layerm : m_regions)
for (const ExtrusionEntity *thin_fill : layerm->thin_fills.entities) { for (const ExtrusionEntity *thin_fill : layerm->thin_fills.entities()) {
ExtrusionEntityCollection *collection = new ExtrusionEntityCollection(); ExtrusionEntityCollection *collection = new ExtrusionEntityCollection();
if (!layerm->fills.can_sort() && layerm->fills.entities.size() > 0 && layerm->fills.entities[0]->is_collection()) { if (!layerm->fills.can_sort() && layerm->fills.entities().size() > 0 && layerm->fills.entities()[0]->is_collection()) {
ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities[0]); ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities()[0]);
if (!no_sort_fill->can_sort() && no_sort_fill->entities.size() > 0 && no_sort_fill->entities[0]->is_collection()) if (!no_sort_fill->can_sort() && no_sort_fill->entities().size() > 0 && no_sort_fill->entities()[0]->is_collection())
static_cast<ExtrusionEntityCollection*>(no_sort_fill->entities[0])->entities.push_back(collection); static_cast<ExtrusionEntityCollection*>(no_sort_fill->entities()[0])->append(ExtrusionEntitiesPtr{ collection });
} else } else
layerm->fills.entities.push_back(collection); layerm->fills.append(ExtrusionEntitiesPtr{ collection });
collection->entities.push_back(thin_fill->clone()); collection->append(*thin_fill);
} }
#ifndef NDEBUG #ifndef NDEBUG
for (LayerRegion *layerm : m_regions) for (LayerRegion *layerm : m_regions)
for (size_t i1 = 0; i1 < layerm->fills.entities.size(); ++i1) { for (size_t i1 = 0; i1 < layerm->fills.entities().size(); ++i1) {
assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities[i1]) != nullptr); assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities()[i1]) != nullptr);
if (!layerm->fills.can_sort() && layerm->fills.entities.size() > 0 && i1 == 0){ if (!layerm->fills.can_sort() && layerm->fills.entities().size() > 0 && i1 == 0){
ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities[0]); ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities()[0]);
assert(no_sort_fill != nullptr); assert(no_sort_fill != nullptr);
assert(!no_sort_fill->empty()); assert(!no_sort_fill->empty());
for (size_t i2 = 0; i2 < no_sort_fill->entities.size(); ++i2) { for (size_t i2 = 0; i2 < no_sort_fill->entities().size(); ++i2) {
ExtrusionEntityCollection* priority_fill = dynamic_cast<ExtrusionEntityCollection*>(no_sort_fill->entities[i2]); ExtrusionEntityCollection* priority_fill = dynamic_cast<ExtrusionEntityCollection*>(no_sort_fill->entities()[i2]);
assert(priority_fill != nullptr); assert(priority_fill != nullptr);
assert(!priority_fill->empty()); assert(!priority_fill->empty());
if (!no_sort_fill->can_sort()) { if (!no_sort_fill->can_sort()) {
for (size_t i3 = 0; i3 < priority_fill->entities.size(); ++i3) for (size_t i3 = 0; i3 < priority_fill->entities().size(); ++i3)
assert(dynamic_cast<ExtrusionEntityCollection*>(priority_fill->entities[i3]) != nullptr); assert(dynamic_cast<ExtrusionEntityCollection*>(priority_fill->entities()[i3]) != nullptr);
} }
} }
} }
@ -780,11 +780,11 @@ void Layer::make_ironing()
if (! polylines.empty()) { if (! polylines.empty()) {
// Save into layer. // Save into layer.
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
ironing_params.layerm->ironings.entities.push_back(eec); ironing_params.layerm->ironings.append(ExtrusionEntitiesPtr{ eec });
// Don't sort the ironing infill lines as they are monotonicly ordered. // Don't sort the ironing infill lines as they are monotonicly ordered.
eec->set_can_sort_reverse(false, false); eec->set_can_sort_reverse(false, false);
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, std::move(polylines), eec->set_entities(), std::move(polylines),
erIroning, erIroning,
flow_mm3_per_mm, float(flow.width), float(height)); flow_mm3_per_mm, float(flow.width), float(height));
} }

View File

@ -218,7 +218,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &para
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
/// push the path /// push the path
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, std::move(polylines), eec->set_entities(), std::move(polylines),
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult * mult_flow, params.flow.mm3_per_mm() * params.flow_mult * mult_flow,
(float)(params.flow.width * params.flow_mult * mult_flow), (float)(params.flow.width * params.flow_mult * mult_flow),
@ -276,10 +276,10 @@ Fill::do_gap_fill(const ExPolygons& gapfill_areas, const FillParams& params, Ext
gap_fill.visit(set_good_role); gap_fill.visit(set_good_role);
}*/ }*/
//move them into the collection //move them into the collection
if (!gap_fill.entities.empty()) { if (!gap_fill.entities().empty()) {
ExtrusionEntityCollection* coll_gapfill = new ExtrusionEntityCollection(); ExtrusionEntityCollection* coll_gapfill = new ExtrusionEntityCollection();
coll_gapfill->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); coll_gapfill->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
coll_gapfill->append(std::move(gap_fill.entities)); coll_gapfill->append(std::move(gap_fill.entities()));
coll_out.push_back(coll_gapfill); coll_out.push_back(coll_gapfill);
} }
} }

View File

@ -230,7 +230,7 @@ public:
void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); } void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); } void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.set_role(new_role); } void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.set_role(new_role); }
void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities) entity->visit(*this); } void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); }
}; };
} // namespace Slic3r } // namespace Slic3r

View File

@ -132,7 +132,7 @@ FillConcentricWGapFill::fill_surface_extrusion(
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection(); ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
coll_nosort->set_can_sort_reverse(false, false); //can be sorted inside the pass coll_nosort->set_can_sort_reverse(false, false); //can be sorted inside the pass
extrusion_entities_append_loops( extrusion_entities_append_loops(
coll_nosort->entities, loops, coll_nosort->set_entities(), loops,
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult, params.flow.mm3_per_mm() * params.flow_mult,
params.flow.width * params.flow_mult, params.flow.width * params.flow_mult,
@ -163,11 +163,11 @@ FillConcentricWGapFill::fill_surface_extrusion(
gap_fill.visit(set_good_role); gap_fill.visit(set_good_role);
} }
//move them into the collection //move them into the collection
coll_nosort->append(std::move(gap_fill.entities)); coll_nosort->append(std::move(gap_fill.entities()));
} }
} }
if (!coll_nosort->entities.empty()) if (!coll_nosort->entities().empty())
out.push_back(coll_nosort); out.push_back(coll_nosort);
else delete coll_nosort; else delete coll_nosort;
} }

View File

@ -3233,12 +3233,12 @@ FillRectilinearPeri::fill_surface_extrusion(const Surface *surface, const FillPa
/// pass the no_sort attribute to the extrusion path /// pass the no_sort attribute to the extrusion path
eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
/// add it into the collection /// add it into the collection
eecroot->entities.push_back(eec); eecroot->append(ExtrusionEntitiesPtr{ eec });
//get the role //get the role
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
/// push the path /// push the path
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, eec->set_entities(),
polylines_1, polylines_1,
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult, params.flow.mm3_per_mm() * params.flow_mult,
@ -3265,12 +3265,12 @@ FillRectilinearPeri::fill_surface_extrusion(const Surface *surface, const FillPa
/// pass the no_sort attribute to the extrusion path /// pass the no_sort attribute to the extrusion path
eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
/// add it into the collection /// add it into the collection
eecroot->entities.push_back(eec); eecroot->append(ExtrusionEntitiesPtr{ eec });
//get the role //get the role
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
/// push the path /// push the path
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, eec->set_entities(),
polylines_2, polylines_2,
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult, params.flow.mm3_per_mm() * params.flow_mult,
@ -3455,7 +3455,7 @@ FillRectilinearSawtooth::fill_surface_extrusion(const Surface *surface, const Fi
idx++; idx++;
} }
if (current_extrusion->size() < 2) extrusions->paths.pop_back(); if (current_extrusion->size() < 2) extrusions->paths.pop_back();
if (!extrusions->paths.empty()) eec->entities.push_back(extrusions); if (!extrusions->paths.empty()) eec->append(ExtrusionEntitiesPtr{ extrusions });
else delete extrusions; else delete extrusions;
} }
// === end === // === end ===
@ -3563,13 +3563,13 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi
eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, polylines_rectilinear, eec->set_entities(), polylines_rectilinear,
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult * flow_mult_exact_volume, params.flow.mm3_per_mm() * params.flow_mult * flow_mult_exact_volume,
params.flow.width * params.flow_mult * float(flow_mult_exact_volume), params.flow.width * params.flow_mult * float(flow_mult_exact_volume),
params.flow.height); params.flow.height);
coll_nosort->entities.push_back(eec); coll_nosort->append(ExtrusionEntitiesPtr{ eec });
unextruded_areas = diff_ex(rectilinear_areas, union_ex(eec->polygons_covered_by_spacing(params.flow.spacing_ratio , 10), true)); unextruded_areas = diff_ex(rectilinear_areas, union_ex(eec->polygons_covered_by_spacing(params.flow.spacing_ratio , 10), true));
} }
@ -3590,7 +3590,7 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi
FillParams params2{ params }; FillParams params2{ params };
params2.role = good_role; params2.role = good_role;
do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, coll_nosort->entities); do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, coll_nosort->set_entities());
} }
// === end === // === end ===

View File

@ -56,8 +56,8 @@ namespace Slic3r {
} }
} }
if (eec->entities.empty()) delete eec; if (eec->entities().empty()) delete eec;
else eecroot.entities.push_back(eec); else eecroot.append(ExtrusionEntitiesPtr{ eec });
} }
void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill, void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
@ -115,7 +115,7 @@ namespace Slic3r {
} }
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec.entities, std::move(polylines_layer), eec.set_entities(), std::move(polylines_layer),
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult * mult_flow, params.flow.mm3_per_mm() * params.flow_mult * mult_flow,
//min-reduced flow width for a better view (it's mostly a gui thing, but some support code can want to mess with it) //min-reduced flow width for a better view (it's mostly a gui thing, but some support code can want to mess with it)
@ -153,7 +153,7 @@ namespace Slic3r {
perform_single_fill(2, *eecroot, *surface, monotonic_params); perform_single_fill(2, *eecroot, *surface, monotonic_params);
} }
if (!eecroot->entities.empty()) if (!eecroot->entities().empty())
out.push_back(eecroot); out.push_back(eecroot);
else delete eecroot; else delete eecroot;

View File

@ -820,7 +820,7 @@ namespace DoExport {
use(path); use(path);
} }
virtual void use(const ExtrusionEntityCollection& collection) override { virtual void use(const ExtrusionEntityCollection& collection) override {
for (const ExtrusionEntity* entity : collection.entities) for (const ExtrusionEntity* entity : collection.entities())
entity->visit(*this); entity->visit(*this);
} }
double reset_use_get(const ExtrusionEntityCollection entity) { reset(); use(entity); return get(); } double reset_use_get(const ExtrusionEntityCollection entity) { reset(); use(entity); return get(); }
@ -892,7 +892,7 @@ namespace DoExport {
// Calculate wiping points if needed // Calculate wiping points if needed
if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) { if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) {
Points skirt_points; Points skirt_points;
for (const ExtrusionEntity *ee : print.skirt().entities) for (const ExtrusionEntity *ee : print.skirt().entities())
for (const ExtrusionPath &path : dynamic_cast<const ExtrusionLoop*>(ee)->paths) for (const ExtrusionPath &path : dynamic_cast<const ExtrusionLoop*>(ee)->paths)
append(skirt_points, path.polyline.points); append(skirt_points, path.polyline.points);
if (! skirt_points.empty()) { if (! skirt_points.empty()) {
@ -2131,7 +2131,7 @@ namespace Skirt {
static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map<uint16_t, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out) static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map<uint16_t, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out)
{ {
// Prime all extruders printing over the 1st layer over the skirt lines. // Prime all extruders printing over the 1st layer over the skirt lines.
size_t n_loops = print.skirt().entities.size(); size_t n_loops = print.skirt().entities().size();
size_t n_tools = layer_tools.extruders.size(); size_t n_tools = layer_tools.extruders.size();
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools; size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
for (size_t i = 0; i < n_loops; i += lines_per_extruder) for (size_t i = 0; i < n_loops; i += lines_per_extruder)
@ -2148,9 +2148,9 @@ namespace Skirt {
// Extrude skirt at the print_z of the raft layers and normal object layers // Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers. // not at the print_z of the interlaced support material layers.
std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out; std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty()) { if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities().empty()) {
if (print.skirt_first_layer()) { if (print.skirt_first_layer()) {
size_t n_loops = print.skirt_first_layer()->entities.size(); size_t n_loops = print.skirt_first_layer()->entities().size();
size_t n_tools = layer_tools.extruders.size(); size_t n_tools = layer_tools.extruders.size();
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools; size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
for (size_t i = 0; i < n_loops; i += lines_per_extruder) for (size_t i = 0; i < n_loops; i += lines_per_extruder)
@ -2174,7 +2174,7 @@ namespace Skirt {
// Extrude skirt at the print_z of the raft layers and normal object layers // Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers. // not at the print_z of the interlaced support material layers.
std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out; std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
if (print.has_skirt() && ! print.skirt().entities.empty() && if (print.has_skirt() && ! print.skirt().entities().empty() &&
// infinite or high skirt does not make sense for sequential print here // infinite or high skirt does not make sense for sequential print here
//(if it is selected, it's done in the "extrude object-only skirt" in process_layer) //(if it is selected, it's done in the "extrude object-only skirt" in process_layer)
// Not enough skirt layers printed yet. // Not enough skirt layers printed yet.
@ -2360,7 +2360,7 @@ void GCode::process_layer(
if (layer_to_print.support_layer != nullptr) { if (layer_to_print.support_layer != nullptr) {
const SupportLayer &support_layer = *layer_to_print.support_layer; const SupportLayer &support_layer = *layer_to_print.support_layer;
const PrintObject &object = *support_layer.object(); const PrintObject &object = *support_layer.object();
if (! support_layer.support_fills.entities.empty()) { if (! support_layer.support_fills.entities().empty()) {
ExtrusionRole role = support_layer.support_fills.role(); ExtrusionRole role = support_layer.support_fills.role();
bool has_support = role == erMixed || role == erSupportMaterial; bool has_support = role == erMixed || role == erSupportMaterial;
bool has_interface = role == erMixed || role == erSupportMaterialInterface; bool has_interface = role == erMixed || role == erSupportMaterialInterface;
@ -2450,7 +2450,7 @@ void GCode::process_layer(
// extrusions represents infill or perimeter extrusions of a single island. // extrusions represents infill or perimeter extrusions of a single island.
assert(dynamic_cast<const ExtrusionEntityCollection*>(ee) != nullptr); assert(dynamic_cast<const ExtrusionEntityCollection*>(ee) != nullptr);
const auto* extrusions = static_cast<const ExtrusionEntityCollection*>(ee); const auto* extrusions = static_cast<const ExtrusionEntityCollection*>(ee);
if (extrusions->entities.empty()) // This shouldn't happen but first_point() would fail. if (extrusions->entities().empty()) // This shouldn't happen but first_point() would fail.
continue; continue;
// This extrusion is part of certain Region, which tells us which extruder should be used for it: // This extrusion is part of certain Region, which tells us which extruder should be used for it:
@ -2505,9 +2505,9 @@ void GCode::process_layer(
} }
} }
}; };
process_entities(ObjectByExtruder::Island::Region::INFILL, layerm->fills.entities); process_entities(ObjectByExtruder::Island::Region::INFILL, layerm->fills.entities());
process_entities(ObjectByExtruder::Island::Region::PERIMETERS, layerm->perimeters.entities); process_entities(ObjectByExtruder::Island::Region::PERIMETERS, layerm->perimeters.entities());
process_entities(ObjectByExtruder::Island::Region::IRONING, layerm->ironings.entities); process_entities(ObjectByExtruder::Island::Region::IRONING, layerm->ironings.entities());
} // for regions } // for regions
} }
} // for objects } // for objects
@ -2540,7 +2540,7 @@ void GCode::process_layer(
const ExtrusionEntityCollection& coll = first_layer && print.skirt_first_layer() ? *print.skirt_first_layer() : print.skirt(); const ExtrusionEntityCollection& coll = first_layer && print.skirt_first_layer() ? *print.skirt_first_layer() : print.skirt();
for (size_t i = loops.first; i < loops.second; ++i) { for (size_t i = loops.first; i < loops.second; ++i) {
// Adjust flow according to this layer's layer height. // Adjust flow according to this layer's layer height.
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(coll.entities[i]); ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(coll.entities()[i]);
for (ExtrusionPath &path : loop.paths) { for (ExtrusionPath &path : loop.paths) {
assert(layer_skirt_flow.height == layer_skirt_flow.height); assert(layer_skirt_flow.height == layer_skirt_flow.height);
assert(mm3_per_mm == mm3_per_mm); assert(mm3_per_mm == mm3_per_mm);
@ -2562,7 +2562,7 @@ void GCode::process_layer(
if (! m_brim_done) { if (! m_brim_done) {
this->set_origin(0., 0.); this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp(); m_avoid_crossing_perimeters.use_external_mp();
for (const ExtrusionEntity* brim_entity : print.brim().entities) { for (const ExtrusionEntity* brim_entity : print.brim().entities()) {
//if first layer, ask for a bigger lift for travel to each brim, to be on the safe side //if first layer, ask for a bigger lift for travel to each brim, to be on the safe side
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id); set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
gcode += this->extrude_entity(*brim_entity, "Brim", m_config.support_material_speed.value); gcode += this->extrude_entity(*brim_entity, "Brim", m_config.support_material_speed.value);
@ -2583,10 +2583,10 @@ void GCode::process_layer(
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift)); this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
if (this->m_layer != nullptr && (this->m_layer->id() < m_config.skirt_height || print.has_infinite_skirt() )) { if (this->m_layer != nullptr && (this->m_layer->id() < m_config.skirt_height || print.has_infinite_skirt() )) {
if(first_layer && print.skirt_first_layer()) if(first_layer && print.skirt_first_layer())
for (const ExtrusionEntity* ee : print_object->skirt_first_layer()->entities) for (const ExtrusionEntity* ee : print_object->skirt_first_layer()->entities())
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value); gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
else else
for (const ExtrusionEntity *ee : print_object->skirt().entities) for (const ExtrusionEntity *ee : print_object->skirt().entities())
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value); gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
} }
} }
@ -2598,7 +2598,7 @@ void GCode::process_layer(
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift)); this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
if (this->m_layer != nullptr && this->m_layer->id() == 0) { if (this->m_layer != nullptr && this->m_layer->id() == 0) {
m_avoid_crossing_perimeters.use_external_mp(true); m_avoid_crossing_perimeters.use_external_mp(true);
for (const ExtrusionEntity *ee : print_object->brim().entities) for (const ExtrusionEntity *ee : print_object->brim().entities())
gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value); gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value);
m_avoid_crossing_perimeters.use_external_mp(false); m_avoid_crossing_perimeters.use_external_mp(false);
m_avoid_crossing_perimeters.disable_once(); m_avoid_crossing_perimeters.disable_once();
@ -3557,12 +3557,12 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::stri
void GCode::use(const ExtrusionEntityCollection &collection) { void GCode::use(const ExtrusionEntityCollection &collection) {
if (!collection.can_sort() || collection.role() == erMixed) { if (!collection.can_sort() || collection.role() == erMixed) {
for (const ExtrusionEntity* next_entity : collection.entities) { for (const ExtrusionEntity* next_entity : collection.entities()) {
next_entity->visit(*this); next_entity->visit(*this);
} }
} else { } else {
ExtrusionEntityCollection chained = collection.chained_path_from(m_last_pos); ExtrusionEntityCollection chained = collection.chained_path_from(m_last_pos);
for (const ExtrusionEntity* next_entity : chained.entities) { for (const ExtrusionEntity* next_entity : chained.entities()) {
next_entity->visit(*this); next_entity->visit(*this);
} }
} }
@ -3719,12 +3719,12 @@ std::string GCode::extrude_ironing(const Print& print, const std::vector<ObjectB
std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills) std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills)
{ {
std::string gcode; std::string gcode;
if (! support_fills.entities.empty()) { if (! support_fills.entities().empty()) {
const char *support_label = "support material"; const char *support_label = "support material";
const char *support_interface_label = "support material interface"; const char *support_interface_label = "support material interface";
const double support_speed = m_config.support_material_speed.value; const double support_speed = m_config.support_material_speed.value;
const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed); const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed);
for (const ExtrusionEntity *ee : support_fills.entities) { for (const ExtrusionEntity *ee : support_fills.entities()) {
ExtrusionRole role = ee->role(); ExtrusionRole role = ee->role();
assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erMixed); assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erMixed);
if (const ExtrusionEntityCollection* coll = dynamic_cast<const ExtrusionEntityCollection*>(ee)) { if (const ExtrusionEntityCollection* coll = dynamic_cast<const ExtrusionEntityCollection*>(ee)) {
@ -4645,7 +4645,7 @@ Point GCode::gcode_to_point(const Vec2d &point) const
scale_(point(1) - m_origin(1) + extruder_offset(1))); scale_(point(1) - m_origin(1) + extruder_offset(1)));
} }
// Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed // Goes through by_region std::vector and returns reference to a subvector of entities(), that are to be printed
// during infill/perimeter wiping, or normally (depends on wiping_entities parameter) // during infill/perimeter wiping, or normally (depends on wiping_entities parameter)
// Fills in by_region_per_copy_cache and returns its reference. // Fills in by_region_per_copy_cache and returns its reference.
const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtruder::Island::by_region_per_copy(std::vector<Region> &by_region_per_copy_cache, unsigned int copy, uint16_t extruder, bool wiping_entities) const const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtruder::Island::by_region_per_copy(std::vector<Region> &by_region_per_copy_cache, unsigned int copy, uint16_t extruder, bool wiping_entities) const
@ -4703,7 +4703,7 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
return by_region_per_copy_cache; return by_region_per_copy_cache;
} }
// This function takes the eec and appends its entities to either perimeters or infills of this Region (depending on the first parameter) // This function takes the eec and appends its entities() to either perimeters or infills of this Region (depending on the first parameter)
// It also saves pointer to ExtruderPerCopy struct (for each entity), that holds information about which extruders should be used for which copy. // It also saves pointer to ExtruderPerCopy struct (for each entity), that holds information about which extruders should be used for which copy.
void GCode::ObjectByExtruder::Island::Region::append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copies_extruder) void GCode::ObjectByExtruder::Island::Region::append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copies_extruder)
{ {
@ -4728,15 +4728,17 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
throw Slic3r::InvalidArgument("Unknown parameter!"); throw Slic3r::InvalidArgument("Unknown parameter!");
} }
// First we append the entities, there are eec->entities.size() of them: // First we append the entities, there are eec->entities().size() of them:
//don't do fill->entities because it will discard no_sort, we must use flatten(preserve_ordering = true) //don't do fill->entities() because it will discard no_sort, we must use flatten(preserve_ordering = true)
// this method will encapsulate every no_sort into an other collection, so we can get the entities directly. // this method will encapsulate every no_sort into an other collection, so we can get the entities() directly.
ExtrusionEntitiesPtr entities = eec->flatten(true).entities; ExtrusionEntityCollection coll = eec->flatten(true);
size_t old_size = perimeters_or_infills->size(); size_t old_size = perimeters_or_infills->size();
size_t new_size = old_size + entities.size(); size_t new_size = old_size + coll.entities().size();
perimeters_or_infills->reserve(new_size); perimeters_or_infills->reserve(new_size);
for (auto* ee : entities) for (ExtrusionEntity* ee : coll.set_entities())
perimeters_or_infills->emplace_back(ee); perimeters_or_infills->push_back(ee);
//hack for change of ownership
coll.set_entities().clear();
if (copies_extruder != nullptr) { if (copies_extruder != nullptr) {
// Don't reallocate overrides if not needed. // Don't reallocate overrides if not needed.

View File

@ -257,12 +257,12 @@ private:
struct Island struct Island
{ {
struct Region { struct Region {
// Non-owned references to LayerRegion::perimeters::entities // Non-owned references to LayerRegion::perimeters::entities()
// std::vector<const ExtrusionEntity*> would be better here, but there is no way in C++ to convert from std::vector<T*> std::vector<const T*> without copying. // std::vector<const ExtrusionEntity*> would be better here, but there is no way in C++ to convert from std::vector<T*> std::vector<const T*> without copying.
ExtrusionEntitiesPtr perimeters; ExtrusionEntitiesPtr perimeters;
// Non-owned references to LayerRegion::fills::entities // Non-owned references to LayerRegion::fills::entities()
ExtrusionEntitiesPtr infills; ExtrusionEntitiesPtr infills;
// Non-owned references to LayerRegion::ironing::entities // Non-owned references to LayerRegion::ironing::entities()
ExtrusionEntitiesPtr ironings; ExtrusionEntitiesPtr ironings;
std::vector<const WipingExtrusions::ExtruderPerCopy*> infills_overrides; std::vector<const WipingExtrusions::ExtruderPerCopy*> infills_overrides;
@ -275,7 +275,7 @@ private:
IRONING, IRONING,
}; };
// Appends perimeter/infill entities and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping // Appends perimeter/infill entities() and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping
void append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copy_extruders); void append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copy_extruders);
}; };

View File

@ -73,7 +73,7 @@ static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_ent
static inline BoundingBoxf extrusionentity_extents(const ExtrusionEntityCollection &extrusion_entity_collection) static inline BoundingBoxf extrusionentity_extents(const ExtrusionEntityCollection &extrusion_entity_collection)
{ {
BoundingBoxf bbox; BoundingBoxf bbox;
for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities) for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities())
bbox.merge(extrusionentity_extents(extrusion_entity)); bbox.merge(extrusionentity_extents(extrusion_entity));
return bbox; return bbox;
} }
@ -114,13 +114,13 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object
BoundingBoxf bbox_this; BoundingBoxf bbox_this;
for (const LayerRegion *layerm : layer->regions()) { for (const LayerRegion *layerm : layer->regions()) {
bbox_this.merge(extrusionentity_extents(layerm->perimeters)); bbox_this.merge(extrusionentity_extents(layerm->perimeters));
for (const ExtrusionEntity *ee : layerm->fills.entities) for (const ExtrusionEntity *ee : layerm->fills.entities())
// fill represents infill extrusions of a single island. // fill represents infill extrusions of a single island.
bbox_this.merge(extrusionentity_extents(*dynamic_cast<const ExtrusionEntityCollection*>(ee))); bbox_this.merge(extrusionentity_extents(*dynamic_cast<const ExtrusionEntityCollection*>(ee)));
} }
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer); const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
if (support_layer) if (support_layer)
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities) for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities())
bbox_this.merge(extrusionentity_extents(extrusion_entity)); bbox_this.merge(extrusionentity_extents(extrusion_entity));
for (const PrintInstance &instance : print_object.instances()) { for (const PrintInstance &instance : print_object.instances()) {
BoundingBoxf bbox_translated(bbox_this); BoundingBoxf bbox_translated(bbox_this);

View File

@ -64,7 +64,7 @@ uint16_t LayerTools::extruder(const ExtrusionEntityCollection &extrusions, const
// 1 based extruder ID. // 1 based extruder ID.
uint16_t extruder = ((this->extruder_override == 0) ? uint16_t extruder = ((this->extruder_override == 0) ?
(is_infill(extrusions.role()) ? (is_infill(extrusions.role()) ?
(is_solid_infill(extrusions.entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) : (is_solid_infill(extrusions.entities().front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) :
region.config().perimeter_extruder.value) : region.config().perimeter_extruder.value) :
this->extruder_override); this->extruder_override);
return (extruder == 0) ? 0 : extruder - 1; return (extruder == 0) ? 0 : extruder - 1;
@ -209,12 +209,12 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
continue; continue;
const PrintRegion &region = *object.print()->regions()[region_id]; const PrintRegion &region = *object.print()->regions()[region_id];
if (! layerm->perimeters.entities.empty()) { if (! layerm->perimeters.entities().empty()) {
bool something_nonoverriddable = true; bool something_nonoverriddable = true;
if (m_print_config_ptr) { // in this case complete_objects is false (see ToolOrdering constructors) if (m_print_config_ptr) { // in this case complete_objects is false (see ToolOrdering constructors)
something_nonoverriddable = false; something_nonoverriddable = false;
for (const auto& eec : layerm->perimeters.entities) // let's check if there are nonoverriddable entities for (const ExtrusionEntity* eec : layerm->perimeters.entities()) // let's check if there are nonoverriddable entities()
if (!layer_tools.wiping_extrusions().is_overriddable_and_mark(dynamic_cast<const ExtrusionEntityCollection&>(*eec), *m_print_config_ptr, object, region)) if (!layer_tools.wiping_extrusions().is_overriddable_and_mark(dynamic_cast<const ExtrusionEntityCollection&>(*eec), *m_print_config_ptr, object, region))
something_nonoverriddable = true; something_nonoverriddable = true;
} }
@ -228,10 +228,10 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
bool has_infill = false; bool has_infill = false;
bool has_solid_infill = false; bool has_solid_infill = false;
bool something_nonoverriddable = false; bool something_nonoverriddable = false;
for (const ExtrusionEntity *ee : layerm->fills.entities) { for (const ExtrusionEntity *ee : layerm->fills.entities()) {
// fill represents infill extrusions of a single island. // fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
ExtrusionRole role = fill->entities.empty() ? erNone : fill->entities.front()->role(); ExtrusionRole role = fill->entities().empty() ? erNone : fill->entities().front()->role();
if (is_solid_infill(role)) if (is_solid_infill(role))
has_solid_infill = true; has_solid_infill = true;
else if (role != erNone) else if (role != erNone)
@ -636,7 +636,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, uint16_t old_
bool wipe_into_infill_only = ! object->config().wipe_into_objects && region.config().wipe_into_infill; bool wipe_into_infill_only = ! object->config().wipe_into_objects && region.config().wipe_into_infill;
if (region.config().infill_first != perimeters_done || wipe_into_infill_only) { if (region.config().infill_first != perimeters_done || wipe_into_infill_only) {
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->fills.entities) { // iterate through all infill Collections for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->fills.entities()) { // iterate through all infill Collections
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (!is_overriddable(*fill, print.config(), *object, region)) if (!is_overriddable(*fill, print.config(), *object, region))
@ -660,7 +660,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, uint16_t old_
// Now the same for perimeters - see comments above for explanation: // Now the same for perimeters - see comments above for explanation:
if (object->config().wipe_into_objects && region.config().infill_first == perimeters_done) if (object->config().wipe_into_objects && region.config().infill_first == perimeters_done)
{ {
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->perimeters.entities) { for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->perimeters.entities()) {
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (is_overriddable(*fill, print.config(), *object, region) && !is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume) { if (is_overriddable(*fill, print.config(), *object, region) && !is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume) {
set_extruder_override(fill, copy, new_extruder, num_of_copies); set_extruder_override(fill, copy, new_extruder, num_of_copies);
@ -680,7 +680,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, uint16_t old_
// Called after all toolchanges on a layer were mark_infill_overridden. There might still be overridable entities, // Called after all toolchanges on a layer were mark_infill_overridden. There might still be overridable entities(),
// that were not actually overridden. If they are part of a dedicated object, printing them with the extruder // that were not actually overridden. If they are part of a dedicated object, printing them with the extruder
// they were initially assigned to might mean violating the perimeter-infill order. We will therefore go through // they were initially assigned to might mean violating the perimeter-infill order. We will therefore go through
// them again and make sure we override it. // them again and make sure we override it.
@ -707,7 +707,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
if (!region.config().wipe_into_infill && !object->config().wipe_into_objects) if (!region.config().wipe_into_infill && !object->config().wipe_into_objects)
continue; continue;
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->fills.entities) { // iterate through all infill Collections for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->fills.entities()) { // iterate through all infill Collections
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (!is_overriddable(*fill, print.config(), *object, region) if (!is_overriddable(*fill, print.config(), *object, region)
@ -730,7 +730,8 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
} }
// Now the same for perimeters - see comments above for explanation: // Now the same for perimeters - see comments above for explanation:
for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->perimeters.entities) { // iterate through all perimeter Collections for (const ExtrusionEntity* ee : this_layer->regions()[region_id]->perimeters.entities()) {
// iterate through all perimeter Collections
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (is_overriddable(*fill, print.config(), *object, region) && ! is_entity_overridden(fill, copy)) if (is_overriddable(*fill, print.config(), *object, region) && ! is_entity_overridden(fill, copy))
set_extruder_override(fill, copy, (region.config().infill_first ? last_nonsoluble_extruder : first_nonsoluble_extruder), num_of_copies); set_extruder_override(fill, copy, (region.config().infill_first ? last_nonsoluble_extruder : first_nonsoluble_extruder), num_of_copies);

View File

@ -35,7 +35,7 @@ public:
// This is called from GCode::process_layer - see implementation for further comments: // This is called from GCode::process_layer - see implementation for further comments:
const ExtruderPerCopy* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies); const ExtruderPerCopy* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies);
// This function goes through all infill entities, decides which ones will be used for wiping and // This function goes through all infill entities(), decides which ones will be used for wiping and
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower: // marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
float mark_wiping_extrusions(const Print& print, uint16_t old_extruder, uint16_t new_extruder, float volume_to_wipe); float mark_wiping_extrusions(const Print& print, uint16_t old_extruder, uint16_t new_extruder, float volume_to_wipe);

View File

@ -86,7 +86,7 @@ public:
void export_region_fill_surfaces_to_svg_debug(const char *name) const; void export_region_fill_surfaces_to_svg_debug(const char *name) const;
// Is there any valid extrusion assigned to this LayerRegion? // Is there any valid extrusion assigned to this LayerRegion?
bool has_extrusions() const { return !this->perimeters.entities.empty() || !this->fills.entities.empty() || !this->ironings.entities.empty() || !this->thin_fills.entities.empty(); } bool has_extrusions() const { return !this->perimeters.entities().empty() || !this->fills.entities().empty() || !this->ironings.entities().empty() || !this->thin_fills.entities().empty(); }
protected: protected:
friend class Layer; friend class Layer;

View File

@ -926,34 +926,34 @@ void PerimeterGenerator::process()
} }
// at this point, all loops should be in contours[0] (= contours.front() ) // at this point, all loops should be in contours[0] (= contours.front() )
// collection of loops to add into loops // collection of loops to add into loops
ExtrusionEntityCollection entities; ExtrusionEntityCollection peri_entities;
if (config->perimeter_loop.value) { if (config->perimeter_loop.value) {
//onlyone_perimter = >fusion all perimeterLoops //onlyone_perimeter = >fusion all perimeterLoops
for (PerimeterGeneratorLoop& loop : contours.front()) { for (PerimeterGeneratorLoop& loop : contours.front()) {
ExtrusionLoop extr_loop = this->_traverse_and_join_loops(loop, get_all_Childs(loop), loop.polygon.points.front()); ExtrusionLoop extr_loop = this->_traverse_and_join_loops(loop, get_all_Childs(loop), loop.polygon.points.front());
//ExtrusionLoop extr_loop = this->_traverse_and_join_loops_old(loop, loop.polygon.points.front(), true); //ExtrusionLoop extr_loop = this->_traverse_and_join_loops_old(loop, loop.polygon.points.front(), true);
extr_loop.paths.back().polyline.points.push_back(extr_loop.paths.front().polyline.points.front()); extr_loop.paths.back().polyline.points.push_back(extr_loop.paths.front().polyline.points.front());
entities.append(extr_loop); peri_entities.append(extr_loop);
} }
// append thin walls // append thin walls
if (!thin_walls_thickpolys.empty()) { if (!thin_walls_thickpolys.empty()) {
if (this->object_config->thin_walls_merge) { if (this->object_config->thin_walls_merge) {
_merge_thin_walls(entities, thin_walls_thickpolys); _merge_thin_walls(peri_entities, thin_walls_thickpolys);
} else { } else {
ExtrusionEntityCollection tw = thin_variable_width ExtrusionEntityCollection tw = thin_variable_width
(thin_walls_thickpolys, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_width / 4, scale_t(this->print_config->resolution))); (thin_walls_thickpolys, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_width / 4, scale_t(this->print_config->resolution)));
entities.append(tw.entities); peri_entities.append(tw.entities());
} }
thin_walls_thickpolys.clear(); thin_walls_thickpolys.clear();
} }
} else { } else {
if (this->object_config->thin_walls_merge) { if (this->object_config->thin_walls_merge) {
ThickPolylines no_thin_walls; ThickPolylines no_thin_walls;
entities = this->_traverse_loops(contours.front(), no_thin_walls); peri_entities = this->_traverse_loops(contours.front(), no_thin_walls);
_merge_thin_walls(entities, thin_walls_thickpolys); _merge_thin_walls(peri_entities, thin_walls_thickpolys);
} else { } else {
entities = this->_traverse_loops(contours.front(), thin_walls_thickpolys); peri_entities = this->_traverse_loops(contours.front(), thin_walls_thickpolys);
} }
} }
@ -968,68 +968,62 @@ void PerimeterGenerator::process()
if (this->config->external_perimeters_hole.value || brim_first_layer) { if (this->config->external_perimeters_hole.value || brim_first_layer) {
//reverse only not-thin wall //reverse only not-thin wall
ExtrusionEntityCollection coll2; ExtrusionEntityCollection coll2;
for (const auto loop : entities.entities) { for (const ExtrusionEntity* loop : peri_entities.entities()) {
if ( (loop->is_loop() && loop->role() != erThinWall)) { if ( (loop->is_loop() && loop->role() != erThinWall)) {
coll2.entities.push_back(loop); coll2.append(*loop);
} }
} }
coll2.reverse(); coll2.reverse();
for (const auto loop : entities.entities) { for (const ExtrusionEntity* loop : peri_entities.entities()) {
if (!((loop->is_loop() && loop->role() != erThinWall))) { if (!((loop->is_loop() && loop->role() != erThinWall))) {
coll2.entities.push_back(loop); coll2.append(*loop);
} }
} }
//note: this hacky thing is possible because coll2.entities contains in fact entities's entities //note: this hacky thing is possible because coll2.entities contains in fact peri_entities's entities
//if you does entities = coll2, you'll delete entities's entities and then you have nothing. //if you does peri_entities = coll2, you'll delete peri_entities's entities() and then you have nothing.
entities.entities = coll2.entities; peri_entities = std::move(coll2);
//and you have to empty coll2 or it will delete his content, hence crashing our hack
coll2.entities.clear();
} else { } else {
//reverse only not-hole perimeters //reverse only not-hole perimeters
ExtrusionEntityCollection coll2; ExtrusionEntityCollection coll2;
for (const auto loop : entities.entities) { for (const ExtrusionEntity* loop : peri_entities.entities()) {
if ((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) { if ((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) {
coll2.entities.push_back(loop); coll2.append(*loop);
} }
} }
coll2.reverse(); coll2.reverse();
for (const auto loop : entities.entities) { for (const ExtrusionEntity* loop : peri_entities.entities()) {
if (!((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) { if (!((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) {
coll2.entities.push_back(loop); coll2.append(*loop);
} }
} }
//note: this hacky thing is possible because coll2.entities contains in fact entities's entities //note: this hacky thing is possible because coll2.entities contains in fact entities's entities
//if you does entities = coll2, you'll delete entities's entities and then you have nothing. //if you does peri_entities = coll2, you'll delete peri_entities's entities and then you have nothing.
entities.entities = coll2.entities; peri_entities = std::move(coll2);
//and you have to empty coll2 or it will delete his content, hence crashing our hack
coll2.entities.clear();
} }
} else if (this->config->external_perimeters_hole.value) { } else if (this->config->external_perimeters_hole.value) {
//reverse the hole, and put them in first place. //reverse the hole, and put them in first place.
ExtrusionEntityCollection coll2; ExtrusionEntityCollection coll2;
for (const auto loop : entities.entities) { for (const ExtrusionEntity* loop : peri_entities.entities()) {
if ((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) { if ((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) {
coll2.entities.push_back(loop); coll2.append(*loop);
} }
} }
coll2.reverse(); coll2.reverse();
for (const auto loop : entities.entities) { for (const ExtrusionEntity* loop : peri_entities.entities()) {
if (!((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) { if (!((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) {
coll2.entities.push_back(loop); coll2.append(*loop);
} }
} }
//note: this hacky thing is possible because coll2.entities contains in fact entities's entities //note: this hacky thing is possible because coll2.entities contains in fact peri_entities's entities
//if you does entities = coll2, you'll delete entities's entities and then you have nothing. //if you does peri_entities = coll2, you'll delete peri_entities's entities and then you have nothing.
entities.entities = coll2.entities; peri_entities = std::move(coll2);
//and you have to empty coll2 or it will delete his content, hence crashing our hack
coll2.entities.clear();
} }
} }
// append perimeters for this slice as a collection // append perimeters for this slice as a collection
if (!entities.empty()) { if (!peri_entities.empty()) {
//move it, to avoid to clone evrything and then delete it //move it, to avoid to clone evrything and then delete it
this->loops->entities.emplace_back(new ExtrusionEntityCollection(std::move(entities))); this->loops->append(peri_entities);
} }
} // for each loop of an island } // for each loop of an island
@ -1116,7 +1110,7 @@ void PerimeterGenerator::process()
// svg.draw(polylines, "blue"); // svg.draw(polylines, "blue");
// svg.Close(); // svg.Close();
//} //}
this->gap_fill->append(gap_fill.entities); this->gap_fill->append(gap_fill.entities());
/* Make sure we don't infill narrow parts that are already gap-filled /* Make sure we don't infill narrow parts that are already gap-filled
(we only consider this surface's gaps to reduce the diff() complexity). (we only consider this surface's gaps to reduce the diff() complexity).
Growing actual extrusions ensures that gaps not filled by medial axis Growing actual extrusions ensures that gaps not filled by medial axis
@ -1130,7 +1124,6 @@ void PerimeterGenerator::process()
// the diff(last, gap) will be done after, as we have to keep the last un-gapped to avoid unneeded gap/infill offset // the diff(last, gap) will be done after, as we have to keep the last un-gapped to avoid unneeded gap/infill offset
} }
} }
//TODO: if a gapfill extrusion is a loop and with width always >= perimeter width then change the type to perimeter and put it at the right place in the loops vector.
// create one more offset to be used as boundary for fill // create one more offset to be used as boundary for fill
// we offset by half the perimeter spacing (to get to the actual infill boundary) // we offset by half the perimeter spacing (to get to the actual infill boundary)
@ -1460,7 +1453,7 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
{ {
// loops is an arrayref of ::Loop objects // loops is an arrayref of ::Loop objects
// turn each one into an ExtrusionLoop object // turn each one into an ExtrusionLoop object
ExtrusionEntityCollection coll; ExtrusionEntitiesPtr coll;
for (const PerimeterGeneratorLoop &loop : loops) { for (const PerimeterGeneratorLoop &loop : loops) {
bool is_external = loop.is_external(); bool is_external = loop.is_external();
@ -1502,20 +1495,20 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
paths.push_back(path); paths.push_back(path);
} }
coll.append(ExtrusionLoop(paths, loop_role)); coll.push_back(new ExtrusionLoop(paths, loop_role));
} }
// append thin walls to the nearest-neighbor search (only for first iteration) // append thin walls to the nearest-neighbor search (only for first iteration)
if (!thin_walls.empty()) { if (!thin_walls.empty()) {
ExtrusionEntityCollection tw = thin_variable_width(thin_walls, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution))); ExtrusionEntityCollection tw = thin_variable_width(thin_walls, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
coll.append(tw.entities); coll.insert(coll.end(), tw.entities().begin(), tw.entities().end());
thin_walls.clear(); thin_walls.clear();
} }
// traverse children and build the final collection // traverse children and build the final collection
Point zero_point(0, 0); Point zero_point(0, 0);
//result is [idx, needReverse] ? //result is [idx, needReverse] ?
std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll.entities, &zero_point); std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll, &zero_point);
ExtrusionEntityCollection coll_out; ExtrusionEntityCollection coll_out;
if (chain.empty()) return coll_out; if (chain.empty()) return coll_out;
@ -1543,34 +1536,34 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
if (idx.first >= loops.size()) { if (idx.first >= loops.size()) {
// this is a thin wall // this is a thin wall
// let's get it from the sorted collection as it might have been reversed // let's get it from the sorted collection as it might have been reversed
coll_out.entities.reserve(coll_out.entities.size() + 1); coll_out.set_entities().reserve(coll_out.entities().size() + 1);
coll_out.entities.emplace_back(coll.entities[idx.first]); coll_out.set_entities().emplace_back(coll[idx.first]);
coll.entities[idx.first] = nullptr; coll[idx.first] = nullptr;
if (idx.second) if (idx.second)
coll_out.entities.back()->reverse(); coll_out.entities().back()->reverse();
//if thin extrusion is a loop, make it ccw like a normal contour. //if thin extrusion is a loop, make it ccw like a normal contour.
if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(coll_out.entities.back())) { if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(coll_out.entities().back())) {
loop->make_counter_clockwise(); loop->make_counter_clockwise();
} }
} else { } else {
const PerimeterGeneratorLoop &loop = loops[idx.first]; const PerimeterGeneratorLoop &loop = loops[idx.first];
assert(thin_walls.empty()); assert(thin_walls.empty());
ExtrusionEntityCollection children = this->_traverse_loops(loop.children, thin_walls); ExtrusionEntityCollection children = this->_traverse_loops(loop.children, thin_walls);
coll_out.entities.reserve(coll_out.entities.size() + children.entities.size() + 1); coll_out.set_entities().reserve(coll_out.entities().size() + children.entities().size() + 1);
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]); ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll[idx.first]);
coll.entities[idx.first] = nullptr; coll[idx.first] = nullptr;
if (loop.is_contour) { if (loop.is_contour) {
//note: this->layer->id() % 2 == 1 already taken into account in the is_steep_overhang compute (to save time). //note: this->layer->id() % 2 == 1 already taken into account in the is_steep_overhang compute (to save time).
if (loop.is_steep_overhang && this->layer->id() % 2 == 1) if (loop.is_steep_overhang && this->layer->id() % 2 == 1)
eloop->make_clockwise(); eloop->make_clockwise();
else else
eloop->make_counter_clockwise(); eloop->make_counter_clockwise();
coll_out.append(std::move(children.entities)); coll_out.append(std::move(children.entities()));
coll_out.append(*eloop); coll_out.append(*eloop);
} else { } else {
eloop->make_clockwise(); eloop->make_clockwise();
coll_out.append(*eloop); coll_out.append(*eloop);
coll_out.append(std::move(children.entities)); coll_out.append(std::move(children.entities()));
} }
} }
} }
@ -1595,7 +1588,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
this->use(path); this->use(path);
} }
virtual void use(ExtrusionEntityCollection &collection) override { virtual void use(ExtrusionEntityCollection &collection) override {
for (ExtrusionEntity *entity : collection.entities) for (ExtrusionEntity *entity : collection.entities())
entity->visit(*this); entity->visit(*this);
} }
}; };
@ -1662,7 +1655,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
virtual void use(ExtrusionEntityCollection &collection) override { virtual void use(ExtrusionEntityCollection &collection) override {
collection.set_can_sort_reverse(true, true); collection.set_can_sort_reverse(true, true);
//for each loop? (or other collections) //for each loop? (or other collections)
for (ExtrusionEntity *entity : collection.entities) for (ExtrusionEntity *entity : collection.entities())
entity->visit(*this); entity->visit(*this);
} }
}; };
@ -1703,7 +1696,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
//create thin wall path exttrusion //create thin wall path exttrusion
ExtrusionEntityCollection tws = thin_variable_width({ tw }, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution))); ExtrusionEntityCollection tws = thin_variable_width({ tw }, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
ChangeFlow change_flow; ChangeFlow change_flow;
if (tws.entities.size() == 1 && tws.entities[0]->is_loop()) { if (tws.entities().size() == 1 && tws.entities()[0]->is_loop()) {
//loop, just add it //loop, just add it
change_flow.percent_extrusion = 1; change_flow.percent_extrusion = 1;
change_flow.use(tws); change_flow.use(tws);
@ -1739,7 +1732,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
//now add thinwalls that have no anchor (make them reversable) //now add thinwalls that have no anchor (make them reversable)
ExtrusionEntityCollection tws = thin_variable_width(not_added, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution))); ExtrusionEntityCollection tws = thin_variable_width(not_added, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
extrusions.append(tws.entities); extrusions.append(tws.entities());
} }
PerimeterIntersectionPoint PerimeterIntersectionPoint

View File

@ -2008,7 +2008,7 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
for (const SupportLayer *layer : object->support_layers()) { for (const SupportLayer *layer : object->support_layers()) {
if (layer->print_z > skirt_height_z) if (layer->print_z > skirt_height_z)
break; break;
for (const ExtrusionEntity *extrusion_entity : layer->support_fills.entities) { for (const ExtrusionEntity *extrusion_entity : layer->support_fills.entities()) {
Polylines poly; Polylines poly;
extrusion_entity->collect_polylines(poly); extrusion_entity->collect_polylines(poly);
for (const Polyline& polyline : poly) for (const Polyline& polyline : poly)
@ -2020,7 +2020,7 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
// get first layer support // get first layer support
if (!object->support_layers().empty() && object->support_layers().front()->print_z == object->m_layers[0]->print_z) { if (!object->support_layers().empty() && object->support_layers().front()->print_z == object->m_layers[0]->print_z) {
Points support_points; Points support_points;
for (const ExtrusionEntity* extrusion_entity : object->support_layers().front()->support_fills.entities) { for (const ExtrusionEntity* extrusion_entity : object->support_layers().front()->support_fills.entities()) {
Polylines poly; Polylines poly;
extrusion_entity->collect_polylines(poly); extrusion_entity->collect_polylines(poly);
for (const Polyline& polyline : poly) for (const Polyline& polyline : poly)
@ -2260,63 +2260,67 @@ void Print::_extrude_brim_from_tree(std::vector<std::vector<BrimLoop>>& loops, c
if (!i_have_line && to_cut.children.empty()) { if (!i_have_line && to_cut.children.empty()) {
//nothing //nothing
} else if (i_have_line && to_cut.children.empty()) { } else if (i_have_line && to_cut.children.empty()) {
ExtrusionEntitiesPtr to_add;
for(Polyline& line : to_cut.lines) for(Polyline& line : to_cut.lines)
if (line.points.back() == line.points.front()) { if (line.points.back() == line.points.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height); ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = line.points; path.polyline.points = line.points;
parent->entities.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt)); to_add.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else { } else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height); ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
parent->entities.push_back(extrusion_path); to_add.emplace_back(extrusion_path);
extrusion_path->polyline = line; extrusion_path->polyline = line;
} }
parent->append(std::move(to_add));
} else if (!i_have_line && !to_cut.children.empty()) { } else if (!i_have_line && !to_cut.children.empty()) {
if (to_cut.children.size() == 1) { if (to_cut.children.size() == 1) {
(*extrude_ptr)(to_cut.children[0], parent); (*extrude_ptr)(to_cut.children[0], parent);
} else { } else {
ExtrusionEntityCollection* mycoll = new ExtrusionEntityCollection(); ExtrusionEntityCollection* mycoll = new ExtrusionEntityCollection();
//mycoll->no_sort = true; //mycoll->no_sort = true;
parent->entities.push_back(mycoll);
for (BrimLoop& child : to_cut.children) for (BrimLoop& child : to_cut.children)
(*extrude_ptr)(child, mycoll); (*extrude_ptr)(child, mycoll);
//remove un-needed collection if possible //remove un-needed collection if possible
if (mycoll->entities.size() == 1) { if (mycoll->entities().size() == 1) {
parent->entities.back() = mycoll->entities.front(); parent->append(*mycoll->entities().front());
mycoll->entities.clear();
delete mycoll; delete mycoll;
} else if (mycoll->entities.size() == 0) { } else if (mycoll->entities().size() == 0) {
parent->remove(parent->entities.size() - 1); delete mycoll;
} else {
parent->append(ExtrusionEntitiesPtr{ mycoll });
} }
} }
} else { } else {
ExtrusionEntityCollection* print_me_first = new ExtrusionEntityCollection(); ExtrusionEntityCollection* print_me_first = new ExtrusionEntityCollection();
parent->entities.push_back(print_me_first); ExtrusionEntitiesPtr to_add;
to_add.emplace_back(print_me_first);
print_me_first->set_can_sort_reverse(false, false); print_me_first->set_can_sort_reverse(false, false);
for (Polyline& line : to_cut.lines) for (Polyline& line : to_cut.lines)
if (line.points.back() == line.points.front()) { if (line.points.back() == line.points.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height); ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = line.points; path.polyline.points = line.points;
print_me_first->entities.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt)); to_add.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else { } else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height); ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
print_me_first->entities.push_back(extrusion_path); to_add.emplace_back(extrusion_path);
extrusion_path->polyline = line; extrusion_path->polyline = line;
} }
parent->append(std::move(to_add));
if (to_cut.children.size() == 1) { if (to_cut.children.size() == 1) {
(*extrude_ptr)(to_cut.children[0], print_me_first); (*extrude_ptr)(to_cut.children[0], print_me_first);
} else { } else {
ExtrusionEntityCollection* children = new ExtrusionEntityCollection(); ExtrusionEntityCollection* children = new ExtrusionEntityCollection();
//children->no_sort = true; //children->no_sort = true;
print_me_first->entities.push_back(children);
for (BrimLoop& child : to_cut.children) for (BrimLoop& child : to_cut.children)
(*extrude_ptr)(child, children); (*extrude_ptr)(child, children);
//remove un-needed collection if possible //remove un-needed collection if possible
if (children->entities.size() == 1) { if (children->entities().size() == 1) {
print_me_first->entities.back() = children->entities.front(); parent->append(*children->entities().front());
children->entities.clear();
delete children; delete children;
} else if (children->entities.size() == 0) { } else if (children->entities().size() == 0) {
print_me_first->remove(parent->entities.size() - 1); delete children;
} else {
parent->append(ExtrusionEntitiesPtr{ children });
} }
} }
} }
@ -2573,7 +2577,7 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex
//push into extrusions //push into extrusions
extrusion_entities_append_paths( extrusion_entities_append_paths(
out.entities, out.set_entities(),
lines_sorted, lines_sorted,
erSkirt, erSkirt,
float(flow.mm3_per_mm()), float(flow.mm3_per_mm()),
@ -2614,7 +2618,7 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex
filler->init_spacing(flow.spacing(), fill_params); filler->init_spacing(flow.spacing(), fill_params);
for (const ExPolygon &expoly : new_brim_area) { for (const ExPolygon &expoly : new_brim_area) {
Surface surface(stPosInternal | stDensSparse, expoly); Surface surface(stPosInternal | stDensSparse, expoly);
filler->fill_surface_extrusion(&surface, fill_params, out.entities); filler->fill_surface_extrusion(&surface, fill_params, out.set_entities());
} }
unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end()); unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end());

View File

@ -1979,7 +1979,7 @@ template<class T> static inline T chain_path_items(const Points &points, const T
return out; return out;
} }
ClipperLib::PolyNodes chain_clipper_polynodes(const Points &points, const ClipperLib::PolyNodes &items) std::vector<ClipperLib::PolyNode*> chain_clipper_polynodes(const Points &points, const std::vector<ClipperLib::PolyNode*> &items)
{ {
return chain_path_items(points, items); return chain_path_items(points, items);
} }

View File

@ -789,9 +789,9 @@ namespace SupportMaterialInternal {
} }
static bool has_bridging_perimeters(const ExtrusionEntityCollection &perimeters) static bool has_bridging_perimeters(const ExtrusionEntityCollection &perimeters)
{ {
for (const ExtrusionEntity *ee : perimeters.entities) { for (const ExtrusionEntity *ee : perimeters.entities()) {
if (ee->is_collection()) { if (ee->is_collection()) {
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) { for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities()) {
//assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !! //assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !!
if (ee2->is_loop()) if (ee2->is_loop())
if (has_bridging_perimeters(*static_cast<const ExtrusionLoop*>(ee2))) if (has_bridging_perimeters(*static_cast<const ExtrusionLoop*>(ee2)))
@ -804,7 +804,7 @@ namespace SupportMaterialInternal {
} }
static bool has_bridging_fills(const ExtrusionEntityCollection &fills) static bool has_bridging_fills(const ExtrusionEntityCollection &fills)
{ {
for (const ExtrusionEntity *ee : fills.entities) { for (const ExtrusionEntity *ee : fills.entities()) {
if (ee->is_collection()) { if (ee->is_collection()) {
if(has_bridging_fills(*static_cast<const ExtrusionEntityCollection*>(ee))) if(has_bridging_fills(*static_cast<const ExtrusionEntityCollection*>(ee)))
return true; return true;
@ -857,7 +857,7 @@ namespace SupportMaterialInternal {
{ {
for (const ExtrusionEntity *ee : perimeters) { for (const ExtrusionEntity *ee : perimeters) {
if (ee->is_collection()) { if (ee->is_collection()) {
collect_bridging_perimeter_areas(static_cast<const ExtrusionEntityCollection*>(ee)->entities, expansion_scaled, out); collect_bridging_perimeter_areas(static_cast<const ExtrusionEntityCollection*>(ee)->entities(), expansion_scaled, out);
} else if (ee->is_loop()) } else if (ee->is_loop())
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee), expansion_scaled, out); collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee), expansion_scaled, out);
} }
@ -2147,7 +2147,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
offset(to_expolygons(region->fill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)), offset(to_expolygons(region->fill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)),
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
if (region->region()->config().overhangs_width.value > 0) if (region->region()->config().overhangs_width.value > 0)
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities, gap_xy_scaled, polygons_trimming); SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities(), gap_xy_scaled, polygons_trimming);
} }
if (! some_region_overlaps) if (! some_region_overlaps)
break; break;
@ -2421,8 +2421,8 @@ struct MyLayerExtruded
*m_polygons_to_extrude = union_(*m_polygons_to_extrude, true); *m_polygons_to_extrude = union_(*m_polygons_to_extrude, true);
} }
// 2) Merge the extrusions. // 2) Merge the extrusions.
this->extrusions.entities.insert(this->extrusions.entities.end(), other.extrusions.entities.begin(), other.extrusions.entities.end()); this->extrusions.set_entities().insert(this->extrusions.entities().end(), other.extrusions.entities().begin(), other.extrusions.entities().end());
other.extrusions.entities.clear(); other.extrusions.set_entities().clear();
// 3) Merge the infill polygons. // 3) Merge the infill polygons.
Slic3r::polygons_append(this->layer->polygons, std::move(other.layer->polygons)); Slic3r::polygons_append(this->layer->polygons, std::move(other.layer->polygons));
this->layer->polygons = union_(this->layer->polygons, true); this->layer->polygons = union_(this->layer->polygons, true);
@ -2671,7 +2671,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
// Transform loops into ExtrusionPath objects. // Transform loops into ExtrusionPath objects.
extrusion_entities_append_paths( extrusion_entities_append_paths(
top_contact_layer.extrusions.entities, top_contact_layer.extrusions.set_entities(),
std::move(loop_lines), std::move(loop_lines),
erSupportMaterialInterface, flow.mm3_per_mm(), flow.width, flow.height); erSupportMaterialInterface, flow.mm3_per_mm(), flow.width, flow.height);
} }
@ -2699,8 +2699,8 @@ public:
virtual void use(const ExtrusionMultiPath3D &multipath) override { if (!multipath.paths.empty()) extrusion_path_template = &multipath.paths.front(); } virtual void use(const ExtrusionMultiPath3D &multipath) override { if (!multipath.paths.empty()) extrusion_path_template = &multipath.paths.front(); }
virtual void use(const ExtrusionLoop &loop) override { if (!loop.paths.empty()) extrusion_path_template = &loop.paths.front(); } virtual void use(const ExtrusionLoop &loop) override { if (!loop.paths.empty()) extrusion_path_template = &loop.paths.front(); }
virtual void use(const ExtrusionEntityCollection &collection) override { virtual void use(const ExtrusionEntityCollection &collection) override {
auto it = collection.entities.begin(); auto it = collection.entities().begin();
while (extrusion_path_template == nullptr && it != collection.entities.end()) { while (extrusion_path_template == nullptr && it != collection.entities().end()) {
(*it)->visit(*this); (*it)->visit(*this);
++it; ++it;
} }
@ -2730,7 +2730,7 @@ void modulate_extrusion_by_overlapping_layers(
// Get the initial extrusion parameters. // Get the initial extrusion parameters.
GetFirstPath getFirstPathVisitor; GetFirstPath getFirstPathVisitor;
flatten_extrusions_in_out.entities.front()->visit(getFirstPathVisitor); flatten_extrusions_in_out.entities().front()->visit(getFirstPathVisitor);
const ExtrusionPath *extrusion_path_template = getFirstPathVisitor.extrusion_path_template; const ExtrusionPath *extrusion_path_template = getFirstPathVisitor.extrusion_path_template;
assert(extrusion_path_template != nullptr); assert(extrusion_path_template != nullptr);
ExtrusionRole extrusion_role = extrusion_path_template->role(); ExtrusionRole extrusion_role = extrusion_path_template->role();
@ -2806,7 +2806,7 @@ void modulate_extrusion_by_overlapping_layers(
// Collect the paths of this_layer. // Collect the paths of this_layer.
{ {
Polylines &polylines = path_fragments.back().polylines; Polylines &polylines = path_fragments.back().polylines;
for (ExtrusionEntitiesPtr::const_iterator it = flatten_extrusions_in_out.entities.begin(); it != flatten_extrusions_in_out.entities.end(); ++it) { for (ExtrusionEntitiesPtr::const_iterator it = flatten_extrusions_in_out.entities().begin(); it != flatten_extrusions_in_out.entities().end(); ++it) {
Polylines polylines_from_entity = (*it)->as_polylines(); Polylines polylines_from_entity = (*it)->as_polylines();
for (Polyline &polyline : polylines_from_entity) { for (Polyline &polyline : polylines_from_entity) {
polylines.emplace_back(std::move(polyline)); polylines.emplace_back(std::move(polyline));
@ -2947,18 +2947,18 @@ void modulate_extrusion_by_overlapping_layers(
if (!multipath.paths.empty()) { if (!multipath.paths.empty()) {
if (multipath.paths.size() == 1) { if (multipath.paths.size() == 1) {
// This path was not fragmented. // This path was not fragmented.
extrusions_in_out.entities.push_back(new ExtrusionPath(std::move(multipath.paths.front()))); extrusions_in_out.append(ExtrusionEntitiesPtr{ new ExtrusionPath(std::move(multipath.paths.front())) });
} else { } else {
// This path was fragmented. Copy the collection as a whole object, so the order inside the collection will not be changed // This path was fragmented. Copy the collection as a whole object, so the order inside the collection will not be changed
// during the chaining of extrusions_in_out. // during the chaining of extrusions_in_out.
extrusions_in_out.entities.push_back(new ExtrusionMultiPath(std::move(multipath))); extrusions_in_out.append(ExtrusionEntitiesPtr{ new ExtrusionMultiPath(std::move(multipath)) });
} }
} }
} }
// If there are any non-consumed fragments, add them separately. // If there are any non-consumed fragments, add them separately.
//FIXME this shall not happen, if the Clipper works as expected and all paths split to fragments could be re-connected. //FIXME this shall not happen, if the Clipper works as expected and all paths split to fragments could be re-connected.
for (auto it_fragment = path_fragments.begin(); it_fragment != path_fragments.end(); ++ it_fragment) for (auto it_fragment = path_fragments.begin(); it_fragment != path_fragments.end(); ++ it_fragment)
extrusion_entities_append_paths(extrusions_in_out.entities, std::move(it_fragment->polylines), extrusion_role, it_fragment->mm3_per_mm, it_fragment->width, it_fragment->height); extrusion_entities_append_paths(extrusions_in_out.set_entities(), std::move(it_fragment->polylines), extrusion_role, it_fragment->mm3_per_mm, it_fragment->width, it_fragment->height);
} }
void PrintObjectSupportMaterial::generate_toolpaths( void PrintObjectSupportMaterial::generate_toolpaths(
@ -3039,7 +3039,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
{ {
assert(support_layer_id < raft_layers.size()); assert(support_layer_id < raft_layers.size());
SupportLayer &support_layer = *object.support_layers()[support_layer_id]; SupportLayer &support_layer = *object.support_layers()[support_layer_id];
assert(support_layer.support_fills.entities.empty()); assert(support_layer.support_fills.entities().empty());
MyLayer &raft_layer = *raft_layers[support_layer_id]; MyLayer &raft_layer = *raft_layers[support_layer_id];
std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(interface_pattern)); std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(interface_pattern));
@ -3068,7 +3068,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// TODO: use offset2_ex() // TODO: use offset2_ex()
to_infill = offset_ex(to_infill, double(- 0.4 * flow.scaled_spacing())); to_infill = offset_ex(to_infill, double(- 0.4 * flow.scaled_spacing()));
extrusion_entities_append_paths( extrusion_entities_append_paths(
support_layer.support_fills.entities, support_layer.support_fills.set_entities(),
to_polylines(std::move(to_infill_polygons)), to_polylines(std::move(to_infill_polygons)),
erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height); erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height);
} }
@ -3080,7 +3080,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
filler->link_max_length = coord_t(scale_(m_support_material_flow.spacing() * link_max_length_factor / support_density)); filler->link_max_length = coord_t(scale_(m_support_material_flow.spacing() * link_max_length_factor / support_density));
fill_expolygons_generate_paths( fill_expolygons_generate_paths(
// Destination // Destination
support_layer.support_fills.entities, support_layer.support_fills.set_entities(),
// Regions to fill // Regions to fill
std::move(to_infill), std::move(to_infill),
// Filler and its parameters // Filler and its parameters
@ -3121,7 +3121,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density)); filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density));
fill_expolygons_generate_paths( fill_expolygons_generate_paths(
// Destination // Destination
support_layer.support_fills.entities, support_layer.support_fills.set_entities(),
// Regions to fill // Regions to fill
offset2_ex(raft_layer.polygons, double(SCALED_EPSILON), double(- SCALED_EPSILON)), offset2_ex(raft_layer.polygons, double(SCALED_EPSILON), double(- SCALED_EPSILON)),
// Filler and its parameters // Filler and its parameters
@ -3260,7 +3260,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
fill_expolygons_generate_paths( fill_expolygons_generate_paths(
// Destination // Destination
layer_ex.extrusions.entities, layer_ex.extrusions.set_entities(),
// Regions to fill // Regions to fill
union_ex(layer_ex.polygons_to_extrude(), true), union_ex(layer_ex.polygons_to_extrude(), true),
// Filler and its parameters // Filler and its parameters
@ -3316,13 +3316,13 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// TODO: use offset2_ex() // TODO: use offset2_ex()
to_infill = offset_ex(to_infill, - 0.4f * float(flow.scaled_spacing())); to_infill = offset_ex(to_infill, - 0.4f * float(flow.scaled_spacing()));
extrusion_entities_append_paths( extrusion_entities_append_paths(
base_layer.extrusions.entities, base_layer.extrusions.set_entities(),
to_polylines(std::move(to_infill_polygons)), to_polylines(std::move(to_infill_polygons)),
erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height); erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height);
} }
fill_expolygons_generate_paths( fill_expolygons_generate_paths(
// Destination // Destination
base_layer.extrusions.entities, base_layer.extrusions.set_entities(),
// Regions to fill // Regions to fill
std::move(to_infill), std::move(to_infill),
// Filler and its parameters // Filler and its parameters

View File

@ -1623,7 +1623,7 @@ void ExtrusionToVert::use(const ExtrusionPath3D &path3D) { _3DScene::extrusionen
void ExtrusionToVert::use(const ExtrusionMultiPath &multipath) { _3DScene::extrusionentity_to_verts(multipath, print_z, copy, volume); } void ExtrusionToVert::use(const ExtrusionMultiPath &multipath) { _3DScene::extrusionentity_to_verts(multipath, print_z, copy, volume); }
void ExtrusionToVert::use(const ExtrusionMultiPath3D &multipath3D) { _3DScene::extrusionentity_to_verts(multipath3D, print_z, copy, volume); } void ExtrusionToVert::use(const ExtrusionMultiPath3D &multipath3D) { _3DScene::extrusionentity_to_verts(multipath3D, print_z, copy, volume); }
void ExtrusionToVert::use(const ExtrusionLoop &loop) { _3DScene::extrusionentity_to_verts(loop, print_z, copy, volume); } void ExtrusionToVert::use(const ExtrusionLoop &loop) { _3DScene::extrusionentity_to_verts(loop, print_z, copy, volume); }
void ExtrusionToVert::use(const ExtrusionEntityCollection &collection) { for (const ExtrusionEntity *extrusion_entity : collection.entities) extrusion_entity->visit(*this); } void ExtrusionToVert::use(const ExtrusionEntityCollection &collection) { for (const ExtrusionEntity *extrusion_entity : collection.entities()) extrusion_entity->visit(*this); }
void _3DScene::extrusionentity_to_verts(const ExtrusionEntity &extrusion_entity, float print_z, const Point &copy, GLVolume &volume) void _3DScene::extrusionentity_to_verts(const ExtrusionEntity &extrusion_entity, float print_z, const Point &copy, GLVolume &volume)
{ {

View File

@ -6102,15 +6102,15 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
_3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy, _3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
volume(idx_layer, layerm->region()->config().perimeter_extruder.value, 0)); volume(idx_layer, layerm->region()->config().perimeter_extruder.value, 0));
if (ctxt.has_infill) { if (ctxt.has_infill) {
for (const ExtrusionEntity *ee : layerm->fills.entities) { for (const ExtrusionEntity *ee : layerm->fills.entities()) {
// fill represents infill extrusions of a single island. // fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee); const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (fill != nullptr && !fill->entities.empty()) if (fill != nullptr && !fill->entities().empty())
_3DScene::extrusionentity_to_verts(*fill, _3DScene::extrusionentity_to_verts(*fill,
float(layer->print_z), float(layer->print_z),
copy, copy,
volume(idx_layer, volume(idx_layer,
is_solid_infill(fill->entities.front()->role()) ? is_solid_infill(fill->entities().front()->role()) ?
layerm->region()->config().solid_infill_extruder : layerm->region()->config().solid_infill_extruder :
layerm->region()->config().infill_extruder, layerm->region()->config().infill_extruder,
1)); 1));
@ -6120,7 +6120,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
if (ctxt.has_support) { if (ctxt.has_support) {
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer); const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
if (support_layer) { if (support_layer) {
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities) for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities())
if (extrusion_entity != nullptr) if (extrusion_entity != nullptr)
_3DScene::extrusionentity_to_verts(*extrusion_entity, float(layer->print_z), copy, _3DScene::extrusionentity_to_verts(*extrusion_entity, float(layer->print_z), copy,
volume(idx_layer, volume(idx_layer,