diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b4d2d7de0..e73b7c073 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -315,6 +315,7 @@ set(SLIC3R_TEST_SOURCES ${TESTDIR}/libslic3r/test_skirt_brim.cpp ${TESTDIR}/libslic3r/test_test_data.cpp ${TESTDIR}/libslic3r/test_trianglemesh.cpp + ${TESTDIR}/libslic3r/test_extrusion_entity.cpp ${TESTDIR}/libslic3r/test_3mf.cpp ) diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.cpp b/xs/src/libslic3r/ExtrusionEntityCollection.cpp index 091cd3ff0..b9f63ff87 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.cpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.cpp @@ -220,25 +220,41 @@ ExtrusionEntityCollection::items_count() const return count; } -/* Returns a single vector of pointers to all non-collection items contained in this one */ +/* Returns a single vector of chained (new) pointers to all non-collection items contained in this one */ void -ExtrusionEntityCollection::flatten(ExtrusionEntityCollection* retval) const +ExtrusionEntityCollection::flatten(ExtrusionEntityCollection* retval, bool preserve_ordering) const { - for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) { - if ((*it)->is_collection()) { - ExtrusionEntityCollection* collection = dynamic_cast(*it); - retval->append(collection->flatten().entities); - } else { - retval->append(**it); + if (this->no_sort and preserve_ordering) { + /// if we want to preserve ordering and we can't sort, break out the unsorted ones first. + ExtrusionEntityCollection *unsortable = new ExtrusionEntityCollection(*this); + retval->append(*unsortable); + unsortable->entities.clear(); + for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) { + if ((*it)->is_collection()) { + ExtrusionEntityCollection* collection = dynamic_cast(*it); + collection->flatten(unsortable, preserve_ordering); + } + else { + unsortable->append(**it); + } + } + } else { + for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) { + if ((*it)->is_collection()) { + ExtrusionEntityCollection* collection = dynamic_cast(*it); + retval->append(collection->flatten(preserve_ordering).entities); + } else { + retval->append(**it); + } } } } ExtrusionEntityCollection -ExtrusionEntityCollection::flatten() const +ExtrusionEntityCollection::flatten(bool preserve_ordering) const { ExtrusionEntityCollection coll; - this->flatten(&coll); + this->flatten(&coll, preserve_ordering); return coll; } diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.hpp b/xs/src/libslic3r/ExtrusionEntityCollection.hpp index eaad7d97b..598f53134 100644 --- a/xs/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/xs/src/libslic3r/ExtrusionEntityCollection.hpp @@ -24,7 +24,7 @@ class ExtrusionEntityCollection : public ExtrusionEntity ExtrusionEntityCollection& operator= (const ExtrusionEntityCollection &other); ~ExtrusionEntityCollection(); - /// Operator to convert and flatten this collection to a single vefctor of ExtrusionPaths. + /// Operator to convert and flatten this collection to a single vector of ExtrusionPaths. operator ExtrusionPaths() const; /// This particular ExtrusionEntity is a collection. @@ -59,11 +59,14 @@ class ExtrusionEntityCollection : public ExtrusionEntity size_t items_count() const; /// Returns a single vector of pointers to all non-collection items contained in this one - void flatten(ExtrusionEntityCollection* retval) const; + /// \param retval a pointer to the output memory space. + /// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False). + void flatten(ExtrusionEntityCollection* retval, bool preserve_ordering = false) const; /// 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). - ExtrusionEntityCollection flatten() const; + /// \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; double min_mm3_per_mm() const; diff --git a/xs/src/libslic3r/PrintGCode.cpp b/xs/src/libslic3r/PrintGCode.cpp index daad3a610..387c17aff 100644 --- a/xs/src/libslic3r/PrintGCode.cpp +++ b/xs/src/libslic3r/PrintGCode.cpp @@ -665,7 +665,7 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) // the ExtrusionPath objects of a certain infill "group" (also called "surface" // throughout the code). We can redefine the order of such Collections but we have to // do each one completely at once. - for(auto* fill : layerm->fills.flatten().entities) { + for(auto* fill : layerm->fills.flatten(true).entities) { if(fill->length() == 0) continue; // this shouldn't happen but first_point() would fail auto extruder_id = fill->is_solid_infill()