diff --git a/xs/src/clipper.cpp b/xs/src/clipper.cpp
index 2b205fd58..4d40d4aa6 100644
--- a/xs/src/clipper.cpp
+++ b/xs/src/clipper.cpp
@@ -595,7 +595,8 @@ void InitEdge2(TEdge& e, PolyType Pt)
 }
 //------------------------------------------------------------------------------
 
-TEdge* RemoveEdge(TEdge* e)
+// Called from ClipperBase::AddPathInternal() to remove collinear and duplicate points.
+inline TEdge* RemoveEdge(TEdge* e)
 {
   //removes e from double_linked_list (but without removing from memory)
   e->Prev->Next = e->Next;
@@ -3486,14 +3487,6 @@ DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2)
 // ClipperOffset class
 //------------------------------------------------------------------------------
 
-ClipperOffset::ClipperOffset(double miterLimit, double arcTolerance)
-{
-  this->MiterLimit = miterLimit;
-  this->ArcTolerance = arcTolerance;
-  m_lowest.X = -1;
-}
-//------------------------------------------------------------------------------
-
 void ClipperOffset::Clear()
 {
   for (int i = 0; i < m_polyNodes.ChildCount(); ++i)
@@ -3512,20 +3505,39 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
   newNode->m_endtype = endType;
 
   //strip duplicate points from path and also get index to the lowest point ...
+  bool   has_shortest_edge_length = ShortestEdgeLength > 0.;
+  double shortest_edge_length2 = has_shortest_edge_length ? ShortestEdgeLength * ShortestEdgeLength : 0.;
   if (endType == etClosedLine || endType == etClosedPolygon)
-    while (highI > 0 && path[0] == path[highI]) highI--;
+    for (; highI > 0; -- highI) {
+      bool same = false;
+      if (has_shortest_edge_length) {
+        double dx = double(path[highI].X - path[0].X);
+        double dy = double(path[highI].Y - path[0].Y);
+        same = dx*dx + dy*dy < shortest_edge_length2;
+      } else
+        same = path[0] == path[highI];
+      if (! same)
+        break;
+    }
   newNode->Contour.reserve(highI + 1);
   newNode->Contour.push_back(path[0]);
   int j = 0, k = 0;
-  for (int i = 1; i <= highI; i++)
-    if (newNode->Contour[j] != path[i])
-    {
-      j++;
-      newNode->Contour.push_back(path[i]);
-      if (path[i].Y > newNode->Contour[k].Y ||
-        (path[i].Y == newNode->Contour[k].Y &&
-        path[i].X < newNode->Contour[k].X)) k = j;
-    }
+  for (int i = 1; i <= highI; i++) {
+    bool same = false;
+    if (has_shortest_edge_length) {
+      double dx = double(path[i].X - newNode->Contour[j].X);
+      double dy = double(path[i].Y - newNode->Contour[j].Y);
+      same = dx*dx + dy*dy < shortest_edge_length2;
+    } else
+      same = newNode->Contour[j] == path[i];
+    if (same)
+      continue;
+    j++;
+    newNode->Contour.push_back(path[i]);
+    if (path[i].Y > newNode->Contour[k].Y ||
+      (path[i].Y == newNode->Contour[k].Y &&
+      path[i].X < newNode->Contour[k].X)) k = j;
+  }
   if (endType == etClosedPolygon && j < 2)
   {
     delete newNode;
@@ -3550,8 +3562,8 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
 
 void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType)
 {
-  for (Paths::size_type i = 0; i < paths.size(); ++i)
-    AddPath(paths[i], joinType, endType);
+  for (const Path &path : paths)
+    AddPath(path, joinType, endType);
 }
 //------------------------------------------------------------------------------
 
diff --git a/xs/src/clipper.hpp b/xs/src/clipper.hpp
index 85bc5cdc4..aabe4f53b 100644
--- a/xs/src/clipper.hpp
+++ b/xs/src/clipper.hpp
@@ -448,7 +448,8 @@ private:
 class ClipperOffset 
 {
 public:
-  ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
+  ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25, double shortestEdgeLength = 0.) :
+    MiterLimit(miterLimit), ArcTolerance(roundPrecision), ShortestEdgeLength(shortestEdgeLength), m_lowest(-1, 0) {}
   ~ClipperOffset() { Clear(); }
   void AddPath(const Path& path, JoinType joinType, EndType endType);
   void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
@@ -457,6 +458,7 @@ public:
   void Clear();
   double MiterLimit;
   double ArcTolerance;
+  double ShortestEdgeLength;
 private:
   Paths m_destPolys;
   Path m_srcPoly;
diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/xs/src/libslic3r/ClipperUtils.cpp
index 8aa72cae4..1a4550248 100644
--- a/xs/src/libslic3r/ClipperUtils.cpp
+++ b/xs/src/libslic3r/ClipperUtils.cpp
@@ -9,6 +9,8 @@
 
 #include <Shiny/Shiny.h>
 
+#define CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR (0.005f)
+
 namespace Slic3r {
 
 #ifdef CLIPPER_UTILS_DEBUG
@@ -210,9 +212,11 @@ ClipperLib::Paths _offset(ClipperLib::Paths &&input, ClipperLib::EndType endType
         co.ArcTolerance = miterLimit;
     else
         co.MiterLimit = miterLimit;
+    float delta_scaled = delta * float(CLIPPER_OFFSET_SCALE);
+    co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
     co.AddPaths(input, joinType, endType);
     ClipperLib::Paths retval;
-    co.Execute(retval, delta * float(CLIPPER_OFFSET_SCALE));
+    co.Execute(retval, delta_scaled);
     
     // unscale output
     unscaleClipperPolygons(retval);
@@ -244,6 +248,7 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
             co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
         else
             co.MiterLimit = miterLimit;
+        co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
         co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
         co.Execute(contours, delta_scaled);
     }
@@ -260,6 +265,7 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygon &expolygon, const float delta,
                 co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
             else
                 co.MiterLimit = miterLimit;
+            co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
             co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
             ClipperLib::Paths out;
             co.Execute(out, - delta_scaled);
@@ -308,6 +314,7 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
                 co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
             else
                 co.MiterLimit = miterLimit;
+            co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
             co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
             co.Execute(contours, delta_scaled);
         }
@@ -331,6 +338,7 @@ ClipperLib::Paths _offset(const Slic3r::ExPolygons &expolygons, const float delt
                         co.ArcTolerance = miterLimit * double(CLIPPER_OFFSET_SCALE);
                     else
                         co.MiterLimit = miterLimit;
+                    co.ShortestEdgeLength = double(std::abs(delta_scaled * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR));
                     co.AddPath(input, joinType, ClipperLib::etClosedPolygon);
                     ClipperLib::Paths out;
                     co.Execute(out, - delta_scaled);
@@ -408,17 +416,20 @@ _offset2(const Polygons &polygons, const float delta1, const float delta2,
     } else {
         co.MiterLimit = miterLimit;
     }
+    float delta_scaled1 = delta1 * float(CLIPPER_OFFSET_SCALE);
+    float delta_scaled2 = delta2 * float(CLIPPER_OFFSET_SCALE);
+    co.ShortestEdgeLength = double(std::max(std::abs(delta_scaled1), std::abs(delta_scaled2)) * CLIPPER_OFFSET_SHORTEST_EDGE_FACTOR);
     
     // perform first offset
     ClipperLib::Paths output1;
     co.AddPaths(input, joinType, ClipperLib::etClosedPolygon);
-    co.Execute(output1, delta1 * float(CLIPPER_OFFSET_SCALE));
+    co.Execute(output1, delta_scaled1);
     
     // perform second offset
     co.Clear();
     co.AddPaths(output1, joinType, ClipperLib::etClosedPolygon);
     ClipperLib::Paths retval;
-    co.Execute(retval, delta2 * float(CLIPPER_OFFSET_SCALE));
+    co.Execute(retval, delta_scaled2);
     
     // unscale output
     unscaleClipperPolygons(retval);
diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp
index 63040718b..88b585307 100644
--- a/xs/src/libslic3r/Point.hpp
+++ b/xs/src/libslic3r/Point.hpp
@@ -38,6 +38,7 @@ class Point
         return Point(scale_(x), scale_(y));
     };
     bool operator==(const Point& rhs) const { return this->x == rhs.x && this->y == rhs.y; }
+    bool operator!=(const Point& rhs) const { return ! (*this == rhs); }
     std::string wkt() const;
     std::string dump_perl() const;
     void scale(double factor);