diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 137ae1847..97599ca07 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -2515,7 +2515,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
         loop.split_at(last_pos, false);
     }
     else
-        m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first, EXTRUDER_CONFIG(nozzle_diameter));
+        m_seam_placer.place_seam(loop, this->last_pos(), m_config.external_perimeters_first,
+                                 EXTRUDER_CONFIG(nozzle_diameter), lower_layer_edge_grid ? lower_layer_edge_grid->get() : nullptr);
 
     // clip the path to avoid the extruder to get exactly on the first point of the loop;
     // if polyline was shorter than the clipping distance we'd get a null polyline, so
@@ -2640,8 +2641,7 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
             m_config.apply(print.get_print_region(&region - &by_region.front()).config());
 
             m_seam_placer.plan_perimeters(std::vector<const ExtrusionEntity*>(region.perimeters.begin(), region.perimeters.end()),
-                *m_layer, m_config.seam_position,
-                m_config.external_perimeters_first, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter),
+                *m_layer, m_config.seam_position, this->last_pos(), EXTRUDER_CONFIG(nozzle_diameter),
                 (m_layer == NULL ? nullptr : m_layer->object()),
                 (lower_layer_edge_grid ? lower_layer_edge_grid.get() : nullptr));
 
diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp
index 609ad4d2d..6d082a431 100644
--- a/src/libslic3r/GCode/SeamPlacer.cpp
+++ b/src/libslic3r/GCode/SeamPlacer.cpp
@@ -293,7 +293,7 @@ void SeamPlacer::init(const Print& print)
 
 
 void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
-                            const Layer& layer, SeamPosition seam_position, bool external_first,
+                            const Layer& layer, SeamPosition seam_position,
                             Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
                             const EdgeGrid::Grid* lower_layer_edge_grid)
 {
@@ -315,20 +315,32 @@ void SeamPlacer::plan_perimeters(const std::vector<const ExtrusionEntity*> perim
                 layer, seam_position, *dynamic_cast<const ExtrusionLoop*>(perimeters[i]), nozzle_dmr,
                 po, lower_layer_edge_grid, last_pos);
             m_plan[i].external = true;
+            m_plan[i].seam_position = seam_position;
+            m_plan[i].layer = &layer;
+            m_plan[i].po = po;
         }
         m_plan[i].pt = last_pos;
     }
 }
 
 
-void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter)
+void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
+                            const EdgeGrid::Grid* lower_layer_edge_grid)
 {
     const double seam_offset = nozzle_diameter;
 
     Point seam = last_pos;
     if (! m_plan.empty() && m_plan_idx < m_plan.size()) {
-        if (m_plan[m_plan_idx].external)
+        if (m_plan[m_plan_idx].external) {
             seam = m_plan[m_plan_idx].pt;
+            // One more heuristics: if the seam is too far from current nozzle position,
+            // try to place it again. This can happen in cases where the external perimeter
+            // does not belong to the preceding ones and they are ordered so they end up
+            // far from each other.
+            if ((seam.cast<double>() - last_pos.cast<double>()).squaredNorm() > std::pow(scale_(5.*nozzle_diameter), 2.))
+                seam = this->calculate_seam(*m_plan[m_plan_idx].layer, m_plan[m_plan_idx].seam_position, loop, nozzle_diameter,
+                                            m_plan[m_plan_idx].po, lower_layer_edge_grid, last_pos);
+        }
         else if (! external_first) {
             // Internal perimeter printed before the external.
             // First get list of external seams.
@@ -342,14 +354,13 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
                 // First find the line segment closest to an external seam:
                 int path_idx = 0;
                 int line_idx = 0;
-                size_t ext_seam_idx = -1;
+                size_t ext_seam_idx = size_t(-1);
                 double min_dist_sqr = std::numeric_limits<double>::max();
-                double nozzle_diameter_sqr = std::pow(scale_(nozzle_diameter), 2.);
                 std::vector<Lines> lines_vect;
-                for (int i = 0; i < loop.paths.size(); ++i) {
+                for (int i = 0; i < int(loop.paths.size()); ++i) {
                     lines_vect.emplace_back(loop.paths[i].polyline.lines());
                     const Lines& lines = lines_vect.back();
-                    for (int j = 0; j < lines.size(); ++j) {
+                    for (int j = 0; j < int(lines.size()); ++j) {
                         for (size_t k : ext_seams) {
                             double d_sqr = lines[j].distance_to_squared(m_plan[k].pt);
                             if (d_sqr < min_dist_sqr) {
@@ -364,7 +375,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
 
                 // Only accept seam that is reasonably close.
                 double limit_dist_sqr = std::pow(double(scale_((ext_seam_idx - m_plan_idx) * nozzle_diameter * 2.)), 2.);
-                if (ext_seam_idx != -1 && min_dist_sqr < limit_dist_sqr) {
+                if (ext_seam_idx != size_t(-1) && min_dist_sqr < limit_dist_sqr) {
                     // Now find a projection of the external seam
                     const Lines& lines = lines_vect[path_idx];
                     Point closest = m_plan[ext_seam_idx].pt.projection_onto(lines[line_idx]);
@@ -377,7 +388,7 @@ void SeamPlacer::place_seam(ExtrusionLoop& loop, const Point& last_pos, bool ext
                     offset -= dist;
                     const Point* a = &closest;
                     const Point* b = &lines[line_idx].b;
-                    while (++line_idx < lines.size() && offset > 0.) {
+                    while (++line_idx < int(lines.size()) && offset > 0.) {
                         last_offset = offset;
                         offset -= lines[line_idx].length();
                         a = &lines[line_idx].a;
diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp
index 5545fcdf9..57c3532c3 100644
--- a/src/libslic3r/GCode/SeamPlacer.hpp
+++ b/src/libslic3r/GCode/SeamPlacer.hpp
@@ -49,11 +49,12 @@ public:
 
 
     void plan_perimeters(const std::vector<const ExtrusionEntity*> perimeters,
-        const Layer& layer, SeamPosition seam_position, bool external_first,
+        const Layer& layer, SeamPosition seam_position,
         Point last_pos, coordf_t nozzle_dmr, const PrintObject* po,
         const EdgeGrid::Grid* lower_layer_edge_grid);
 
-    void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter);
+    void place_seam(ExtrusionLoop& loop, const Point& last_pos, bool external_first, double nozzle_diameter,
+                    const EdgeGrid::Grid* lower_layer_edge_grid);
     
 
     using TreeType = AABBTreeIndirect::Tree<2, coord_t>;
@@ -80,6 +81,9 @@ private:
         Point pt;
         bool precalculated = false;
         bool external = false;
+        const Layer* layer = nullptr;
+        SeamPosition seam_position;
+        const PrintObject* po = nullptr;
     };
     std::vector<SeamPoint> m_plan;
     size_t m_plan_idx;