From 9038dc21e85d1aa956fcb0429659884d028dee66 Mon Sep 17 00:00:00 2001
From: bubnikv <bubnikv@gmail.com>
Date: Fri, 10 Jan 2020 15:51:35 +0100
Subject: [PATCH] Fixing regression issue after G-code export refactoring.

---
 src/libslic3r/ExtrusionEntityCollection.cpp | 39 ++++++++++++++-------
 src/libslic3r/ExtrusionEntityCollection.hpp | 19 ++++++++--
 src/libslic3r/GCode.cpp                     |  6 ++--
 3 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/src/libslic3r/ExtrusionEntityCollection.cpp b/src/libslic3r/ExtrusionEntityCollection.cpp
index 7e0e1fc9c..147a60d95 100644
--- a/src/libslic3r/ExtrusionEntityCollection.cpp
+++ b/src/libslic3r/ExtrusionEntityCollection.cpp
@@ -6,6 +6,26 @@
 
 namespace Slic3r {
 
+void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role)
+{
+	if (role != erMixed) {
+		auto first  = extrusion_entities.begin();
+		auto last   = extrusion_entities.end();
+		auto result = first;
+		while (first != last) {
+		    // The caller wants only paths with a specific extrusion role.
+		    auto role2 = (*first)->role();
+		    if (role != role2) {
+		        // This extrusion entity does not match the role asked.
+		        assert(role2 != erMixed);
+		        *result = *first;
+	  			++ result;
+		    }
+			++ first;
+		}
+	}
+}
+
 ExtrusionEntityCollection::ExtrusionEntityCollection(const ExtrusionPaths &paths)
     : no_sort(false)
 {
@@ -76,19 +96,12 @@ void ExtrusionEntityCollection::remove(size_t i)
 
 ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const ExtrusionEntitiesPtr& extrusion_entities, const Point &start_near, ExtrusionRole role)
 {
-	ExtrusionEntityCollection out;
-	for (const ExtrusionEntity *ee : extrusion_entities) {
-		if (role != erMixed) {
-		    // The caller wants only paths with a specific extrusion role.
-		    auto role2 = ee->role();
-		    if (role != role2) {
-		        // This extrusion entity does not match the role asked.
-		        assert(role2 != erMixed);
-		        continue;
-		    }
-		}
-		out.entities.emplace_back(ee->clone());
-	}
+	// Return a filtered copy of the collection.
+    ExtrusionEntityCollection out;
+    out.entities = filter_by_extrusion_role(extrusion_entities, role);
+	// Clone the extrusion entities.
+	for (auto &ptr : out.entities)
+		ptr = ptr->clone();
 	chain_and_reorder_extrusion_entities(out.entities, &start_near);
     return out;
 }
diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp
index e529bea02..8aacb4d46 100644
--- a/src/libslic3r/ExtrusionEntityCollection.hpp
+++ b/src/libslic3r/ExtrusionEntityCollection.hpp
@@ -6,6 +6,21 @@
 
 namespace Slic3r {
 
+// Remove those items from extrusion_entities, that do not match role.
+// Do nothing if role is mixed.
+// Removed elements are NOT being deleted.
+void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role);
+
+// Return new vector of ExtrusionEntities* with only those items from input extrusion_entities, that match role.
+// Return all extrusion entities if role is mixed.
+// Returned extrusion entities are shared with the source vector, they are NOT cloned, they are considered to be owned by extrusion_entities.
+inline ExtrusionEntitiesPtr filter_by_extrusion_role(const ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role)
+{
+	ExtrusionEntitiesPtr out { extrusion_entities }; 
+	filter_by_extrusion_role_in_place(out, role);
+	return out;
+}
+
 class ExtrusionEntityCollection : public ExtrusionEntity
 {
 public:
@@ -67,7 +82,7 @@ public:
     void remove(size_t i);
     static ExtrusionEntityCollection chained_path_from(const ExtrusionEntitiesPtr &extrusion_entities, const Point &start_near, ExtrusionRole role = erMixed);
     ExtrusionEntityCollection chained_path_from(const Point &start_near, ExtrusionRole role = erMixed) const 
-    	{ return (this->no_sort || role == erMixed) ? *this : chained_path_from(this->entities, start_near, role); }
+    	{ return this->no_sort ? *this : chained_path_from(this->entities, start_near, role); }
     void reverse();
     const Point& first_point() const { return this->entities.front()->first_point(); }
     const Point& last_point() const { return this->entities.back()->last_point(); }
@@ -107,6 +122,6 @@ public:
     }
 };
 
-}
+} // namespace Slic3r
 
 #endif
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 7bd352537..942558f27 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -2848,9 +2848,9 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
     std::string gcode;
     for (const ObjectByExtruder::Island::Region &region : by_region) {
         m_config.apply(print.regions()[&region - &by_region.front()]->config());
-//        for (ExtrusionEntity *fill : ExtrusionEntityCollection::chained_path_from(region.infills, m_last_pos).entities) {
-        // Don't sort the infills, they contain gap fill, which shall be extruded after normal fills.
-        for (const ExtrusionEntity *fill : region.infills) {
+		ExtrusionEntitiesPtr extrusions { region.infills };
+		chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
+        for (const ExtrusionEntity *fill : extrusions) {
             auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
             if (eec) {
 				for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)