From 14b32c4f166f094bc10fae06c88c5234cd94b292 Mon Sep 17 00:00:00 2001
From: tamasmeszaros <meszaros.q@gmail.com>
Date: Wed, 26 Jun 2019 10:33:42 +0200
Subject: [PATCH 1/2] Make an order in using scale and unscale, remove some
 warnings.

---
 src/libnest2d/tests/test.cpp         | 552 +++++++++++++--------------
 src/libslic3r/MTUtils.hpp            |  91 +++++
 src/libslic3r/MinAreaBoundingBox.cpp |  68 ++--
 src/libslic3r/ModelArrange.cpp       |   2 +-
 src/libslic3r/SLA/SLABasePool.cpp    |  15 +-
 src/libslic3r/SLAPrint.cpp           |  34 +-
 src/libslic3r/libslic3r.h            |  14 -
 7 files changed, 408 insertions(+), 368 deletions(-)

diff --git a/src/libnest2d/tests/test.cpp b/src/libnest2d/tests/test.cpp
index 5741e87b4..363a3930c 100644
--- a/src/libnest2d/tests/test.cpp
+++ b/src/libnest2d/tests/test.cpp
@@ -10,10 +10,6 @@
 #include "boost/multiprecision/integer.hpp"
 #include "boost/rational.hpp"
 
-//#include "../tools/Int128.hpp"
-
-//#include "gte/Mathematics/GteMinimumAreaBox2.h"
-
 //#include "../tools/libnfpglue.hpp"
 //#include "../tools/nfp_svgnest_glue.hpp"
 
@@ -42,151 +38,151 @@ struct NfpImpl<S, NfpLevel::CONVEX_ONLY>
 
 std::vector<libnest2d::Item>& prusaParts() {
     static std::vector<libnest2d::Item> ret;
-
+    
     if(ret.empty()) {
         ret.reserve(PRINTER_PART_POLYGONS.size());
         for(auto& inp : PRINTER_PART_POLYGONS) ret.emplace_back(inp);
     }
-
+    
     return ret;
 }
 
 TEST(BasicFunctionality, Angles)
 {
-
+    
     using namespace libnest2d;
-
+    
     Degrees deg(180);
     Radians rad(deg);
     Degrees deg2(rad);
-
+    
     ASSERT_DOUBLE_EQ(rad, Pi);
     ASSERT_DOUBLE_EQ(deg, 180);
     ASSERT_DOUBLE_EQ(deg2, 180);
     ASSERT_DOUBLE_EQ(rad, Radians(deg));
     ASSERT_DOUBLE_EQ( Degrees(rad), deg);
-
+    
     ASSERT_TRUE(rad == deg);
-
+    
     Segment seg = {{0, 0}, {12, -10}};
-
+    
     ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 270 &&
                 Degrees(seg.angleToXaxis()) < 360);
-
+    
     seg = {{0, 0}, {12, 10}};
-
+    
     ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 0 &&
                 Degrees(seg.angleToXaxis()) < 90);
-
+    
     seg = {{0, 0}, {-12, 10}};
-
+    
     ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 90 &&
                 Degrees(seg.angleToXaxis()) < 180);
-
+    
     seg = {{0, 0}, {-12, -10}};
-
+    
     ASSERT_TRUE(Degrees(seg.angleToXaxis()) > 180 &&
                 Degrees(seg.angleToXaxis()) < 270);
-
+    
     seg = {{0, 0}, {1, 0}};
-
+    
     ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 0);
-
+    
     seg = {{0, 0}, {0, 1}};
-
+    
     ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 90);
-
-
+    
+    
     seg = {{0, 0}, {-1, 0}};
-
+    
     ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 180);
-
-
+    
+    
     seg = {{0, 0}, {0, -1}};
-
+    
     ASSERT_DOUBLE_EQ(Degrees(seg.angleToXaxis()), 270);
-
+    
 }
 
 // Simple test, does not use gmock
 TEST(BasicFunctionality, creationAndDestruction)
 {
     using namespace libnest2d;
-
+    
     Item sh = { {0, 0}, {1, 0}, {1, 1}, {0, 1} };
-
+    
     ASSERT_EQ(sh.vertexCount(), 4u);
-
+    
     Item sh2 ({ {0, 0}, {1, 0}, {1, 1}, {0, 1} });
-
+    
     ASSERT_EQ(sh2.vertexCount(), 4u);
-
+    
     // copy
     Item sh3 = sh2;
-
+    
     ASSERT_EQ(sh3.vertexCount(), 4u);
-
+    
     sh2 = {};
-
+    
     ASSERT_EQ(sh2.vertexCount(), 0u);
     ASSERT_EQ(sh3.vertexCount(), 4u);
-
+    
 }
 
 TEST(GeometryAlgorithms, boundingCircle) {
     using namespace libnest2d;
     using placers::boundingCircle;
-
+    
     PolygonImpl p = {{{0, 10}, {10, 0}, {0, -10}, {0, 10}}, {}};
     Circle c = boundingCircle(p);
-
+    
     ASSERT_EQ(c.center().X, 0);
     ASSERT_EQ(c.center().Y, 0);
     ASSERT_DOUBLE_EQ(c.radius(), 10);
-
+    
     shapelike::translate(p, PointImpl{10, 10});
     c = boundingCircle(p);
-
+    
     ASSERT_EQ(c.center().X, 10);
     ASSERT_EQ(c.center().Y, 10);
     ASSERT_DOUBLE_EQ(c.radius(), 10);
-
+    
     auto parts = prusaParts();
-
+    
     int i = 0;
     for(auto& part : parts) {
         c = boundingCircle(part.transformedShape());
         if(std::isnan(c.radius())) std::cout << "fail: radius is nan" << std::endl;
-
+        
         else for(auto v : shapelike::contour(part.transformedShape()) ) {
-            auto d = pointlike::distance(v, c.center());
-            if(d > c.radius() ) {
-                auto e = std::abs( 1.0 - d/c.radius());
-                ASSERT_LE(e, 1e-3);
+                auto d = pointlike::distance(v, c.center());
+                if(d > c.radius() ) {
+                    auto e = std::abs( 1.0 - d/c.radius());
+                    ASSERT_LE(e, 1e-3);
+                }
             }
-        }
         i++;
     }
-
+    
 }
 
 TEST(GeometryAlgorithms, Distance) {
     using namespace libnest2d;
-
+    
     Point p1 = {0, 0};
-
+    
     Point p2 = {10, 0};
     Point p3 = {10, 10};
-
+    
     ASSERT_DOUBLE_EQ(pointlike::distance(p1, p2), 10);
     ASSERT_DOUBLE_EQ(pointlike::distance(p1, p3), sqrt(200));
-
+    
     Segment seg(p1, p3);
-
-//    ASSERT_DOUBLE_EQ(pointlike::distance(p2, seg), 7.0710678118654755);
-
+    
+    //    ASSERT_DOUBLE_EQ(pointlike::distance(p2, seg), 7.0710678118654755);
+    
     auto result = pointlike::horizontalDistance(p2, seg);
-
+    
     auto check = [](TCompute<Coord> val, TCompute<Coord> expected) {
         if(std::is_floating_point<TCompute<Coord>>::value)
             ASSERT_DOUBLE_EQ(static_cast<double>(val),
@@ -194,44 +190,44 @@ TEST(GeometryAlgorithms, Distance) {
         else
             ASSERT_EQ(val, expected);
     };
-
+    
     ASSERT_TRUE(result.second);
     check(result.first, 10);
-
+    
     result = pointlike::verticalDistance(p2, seg);
     ASSERT_TRUE(result.second);
     check(result.first, -10);
-
+    
     result = pointlike::verticalDistance(Point{10, 20}, seg);
     ASSERT_TRUE(result.second);
     check(result.first, 10);
-
-
+    
+    
     Point p4 = {80, 0};
     Segment seg2 = { {0, 0}, {0, 40} };
-
+    
     result = pointlike::horizontalDistance(p4, seg2);
-
+    
     ASSERT_TRUE(result.second);
     check(result.first, 80);
-
+    
     result = pointlike::verticalDistance(p4, seg2);
     // Point should not be related to the segment
     ASSERT_FALSE(result.second);
-
+    
 }
 
 TEST(GeometryAlgorithms, Area) {
     using namespace libnest2d;
-
+    
     Rectangle rect(10, 10);
-
+    
     ASSERT_EQ(rect.area(), 100);
-
+    
     Rectangle rect2 = {100, 100};
-
+    
     ASSERT_EQ(rect2.area(), 10000);
-
+    
     Item item = {
         {61, 97},
         {70, 151},
@@ -242,33 +238,33 @@ TEST(GeometryAlgorithms, Area) {
         {61, 77},
         {61, 97}
     };
-
+    
     ASSERT_TRUE(shapelike::area(item.transformedShape()) > 0 );
 }
 
 TEST(GeometryAlgorithms, IsPointInsidePolygon) {
     using namespace libnest2d;
-
+    
     Rectangle rect(10, 10);
-
+    
     Point p = {1, 1};
-
+    
     ASSERT_TRUE(rect.isInside(p));
-
+    
     p = {11, 11};
-
+    
     ASSERT_FALSE(rect.isInside(p));
-
-
+    
+    
     p = {11, 12};
-
+    
     ASSERT_FALSE(rect.isInside(p));
-
-
+    
+    
     p = {3, 3};
-
+    
     ASSERT_TRUE(rect.isInside(p));
-
+    
 }
 
 //TEST(GeometryAlgorithms, Intersections) {
@@ -294,21 +290,21 @@ TEST(GeometryAlgorithms, LeftAndDownPolygon)
 {
     using namespace libnest2d;
     using namespace libnest2d;
-
+    
     Box bin(100, 100);
     BottomLeftPlacer placer(bin);
-
+    
     Item item = {{70, 75}, {88, 60}, {65, 50}, {60, 30}, {80, 20}, {42, 20},
                  {35, 35}, {35, 55}, {40, 75}, {70, 75}};
-
+    
     Item leftControl = { {40, 75},
-                         {35, 55},
-                         {35, 35},
-                         {42, 20},
-                         {0,  20},
-                         {0,  75},
-                         {40, 75}};
-
+                        {35, 55},
+                        {35, 35},
+                        {42, 20},
+                        {0,  20},
+                        {0,  75},
+                        {40, 75}};
+    
     Item downControl = {{88, 60},
                         {88, 0},
                         {35, 0},
@@ -318,22 +314,22 @@ TEST(GeometryAlgorithms, LeftAndDownPolygon)
                         {60, 30},
                         {65, 50},
                         {88, 60}};
-
+    
     Item leftp(placer.leftPoly(item));
-
+    
     ASSERT_TRUE(shapelike::isValid(leftp.rawShape()).first);
     ASSERT_EQ(leftp.vertexCount(), leftControl.vertexCount());
-
+    
     for(unsigned long i = 0; i < leftControl.vertexCount(); i++) {
         ASSERT_EQ(getX(leftp.vertex(i)), getX(leftControl.vertex(i)));
         ASSERT_EQ(getY(leftp.vertex(i)), getY(leftControl.vertex(i)));
     }
-
+    
     Item downp(placer.downPoly(item));
-
+    
     ASSERT_TRUE(shapelike::isValid(downp.rawShape()).first);
     ASSERT_EQ(downp.vertexCount(), downControl.vertexCount());
-
+    
     for(unsigned long i = 0; i < downControl.vertexCount(); i++) {
         ASSERT_EQ(getX(downp.vertex(i)), getX(downControl.vertex(i)));
         ASSERT_EQ(getY(downp.vertex(i)), getY(downControl.vertex(i)));
@@ -344,7 +340,7 @@ TEST(GeometryAlgorithms, LeftAndDownPolygon)
 TEST(GeometryAlgorithms, ArrangeRectanglesTight)
 {
     using namespace libnest2d;
-
+    
     std::vector<Rectangle> rects = {
         {80, 80},
         {60, 90},
@@ -366,17 +362,17 @@ TEST(GeometryAlgorithms, ArrangeRectanglesTight)
         {5, 5},
         {5, 5},
         {20, 20} };
-
-
+    
+    
     Nester<BottomLeftPlacer, DJDHeuristic> arrange(Box(210, 250));
-
+    
     auto groups = arrange(rects.begin(), rects.end());
-
+    
     ASSERT_EQ(groups.size(), 1u);
     ASSERT_EQ(groups[0].size(), rects.size());
-
+    
     // check for no intersections, no containment:
-
+    
     for(auto result : groups) {
         bool valid = true;
         for(Item& r1 : result) {
@@ -389,14 +385,14 @@ TEST(GeometryAlgorithms, ArrangeRectanglesTight)
             }
         }
     }
-
+    
 }
 
 TEST(GeometryAlgorithms, ArrangeRectanglesLoose)
 {
     using namespace libnest2d;
-
-//    std::vector<Rectangle> rects = { {40, 40}, {10, 10}, {20, 20} };
+    
+    //    std::vector<Rectangle> rects = { {40, 40}, {10, 10}, {20, 20} };
     std::vector<Rectangle> rects = {
         {80, 80},
         {60, 90},
@@ -418,17 +414,17 @@ TEST(GeometryAlgorithms, ArrangeRectanglesLoose)
         {5, 5},
         {5, 5},
         {20, 20} };
-
+    
     Coord min_obj_distance = 5;
-
+    
     Nester<BottomLeftPlacer, DJDHeuristic> arrange(Box(210, 250),
-                                                     min_obj_distance);
-
+                                                   min_obj_distance);
+    
     auto groups = arrange(rects.begin(), rects.end());
-
+    
     ASSERT_EQ(groups.size(), 1u);
     ASSERT_EQ(groups[0].size(), rects.size());
-
+    
     // check for no intersections, no containment:
     auto result = groups[0];
     bool valid = true;
@@ -441,7 +437,7 @@ TEST(GeometryAlgorithms, ArrangeRectanglesLoose)
             }
         }
     }
-
+    
 }
 
 namespace {
@@ -449,68 +445,68 @@ using namespace libnest2d;
 
 template<long long SCALE = 1, class Bin>
 void exportSVG(std::vector<std::reference_wrapper<Item>>& result, const Bin& bin, int idx = 0) {
-
-
+    
+    
     std::string loc = "out";
-
+    
     static std::string svg_header =
-R"raw(<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+        R"raw(<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
 <svg height="500" width="500" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 )raw";
-
+    
     int i = idx;
     auto r = result;
-//    for(auto r : result) {
-        std::fstream out(loc + std::to_string(i) + ".svg", std::fstream::out);
-        if(out.is_open()) {
-            out << svg_header;
-            Item rbin( Rectangle(bin.width(), bin.height()) );
-            for(unsigned i = 0; i < rbin.vertexCount(); i++) {
-                auto v = rbin.vertex(i);
-                setY(v, -getY(v)/SCALE + 500 );
-                setX(v, getX(v)/SCALE);
-                rbin.setVertex(i, v);
-            }
-            out << shapelike::serialize<Formats::SVG>(rbin.rawShape()) << std::endl;
-            for(Item& sh : r) {
-                Item tsh(sh.transformedShape());
-                for(unsigned i = 0; i < tsh.vertexCount(); i++) {
-                    auto v = tsh.vertex(i);
-                    setY(v, -getY(v)/SCALE + 500);
-                    setX(v, getX(v)/SCALE);
-                    tsh.setVertex(i, v);
-                }
-                out << shapelike::serialize<Formats::SVG>(tsh.rawShape()) << std::endl;
-            }
-            out << "\n</svg>" << std::endl;
+    //    for(auto r : result) {
+    std::fstream out(loc + std::to_string(i) + ".svg", std::fstream::out);
+    if(out.is_open()) {
+        out << svg_header;
+        Item rbin( Rectangle(bin.width(), bin.height()) );
+        for(unsigned i = 0; i < rbin.vertexCount(); i++) {
+            auto v = rbin.vertex(i);
+            setY(v, -getY(v)/SCALE + 500 );
+            setX(v, getX(v)/SCALE);
+            rbin.setVertex(i, v);
         }
-        out.close();
-
-//        i++;
-//    }
+        out << shapelike::serialize<Formats::SVG>(rbin.rawShape()) << std::endl;
+        for(Item& sh : r) {
+            Item tsh(sh.transformedShape());
+            for(unsigned i = 0; i < tsh.vertexCount(); i++) {
+                auto v = tsh.vertex(i);
+                setY(v, -getY(v)/SCALE + 500);
+                setX(v, getX(v)/SCALE);
+                tsh.setVertex(i, v);
+            }
+            out << shapelike::serialize<Formats::SVG>(tsh.rawShape()) << std::endl;
+        }
+        out << "\n</svg>" << std::endl;
+    }
+    out.close();
+    
+    //        i++;
+    //    }
 }
 }
 
 TEST(GeometryAlgorithms, BottomLeftStressTest) {
     using namespace libnest2d;
-
+    
     const Coord SCALE = 1000000;
     auto& input = prusaParts();
-
+    
     Box bin(210*SCALE, 250*SCALE);
     BottomLeftPlacer placer(bin);
-
+    
     auto it = input.begin();
     auto next = it;
     int i = 0;
     while(it != input.end() && ++next != input.end()) {
         placer.pack(*it);
         placer.pack(*next);
-
+        
         auto result = placer.getItems();
         bool valid = true;
-
+        
         if(result.size() == 2) {
             Item& r1 = result[0];
             Item& r2 = result[1];
@@ -525,7 +521,7 @@ TEST(GeometryAlgorithms, BottomLeftStressTest) {
             std::cout << "something went terribly wrong!" << std::endl;
             FAIL();
         }
-
+        
         placer.clearItems();
         it++;
         i++;
@@ -534,9 +530,9 @@ TEST(GeometryAlgorithms, BottomLeftStressTest) {
 
 TEST(GeometryAlgorithms, convexHull) {
     using namespace libnest2d;
-
+    
     ClipperLib::Path poly = PRINTER_PART_POLYGONS[0];
-
+    
     auto chull = sl::convexHull(poly);
     
     ASSERT_EQ(chull.size(), poly.size());
@@ -545,7 +541,7 @@ TEST(GeometryAlgorithms, convexHull) {
 
 TEST(GeometryAlgorithms, NestTest) {
     std::vector<Item> input = prusaParts();
-
+    
     PackGroup result = libnest2d::nest(input,
                                        Box(250000000, 210000000),
                                        [](unsigned cnt) {
@@ -553,16 +549,17 @@ TEST(GeometryAlgorithms, NestTest) {
                                                << "parts left: " << cnt
                                                << std::endl;
                                        });
-
+    
     ASSERT_LE(result.size(), 2);
-
-    int partsum = std::accumulate(result.begin(),
-                                  result.end(),
-                                  0,
-                                  [](int s,
-                                     const decltype(result)::value_type &bin) {
-                                      return s += bin.size();
-                                  });
+    
+    size_t partsum = std::accumulate(result.begin(),
+                                     result.end(),
+                                     size_t(0),
+                                     [](int s,
+                                        const decltype(
+                                            result)::value_type &bin) {
+                                         return s += bin.size();
+                                     });
     
     ASSERT_EQ(input.size(), partsum);
 }
@@ -647,7 +644,7 @@ std::vector<ItemPair> nfp_testdata = {
             {118, 101},
             {117, 103},
             {117, 107}
-        },
+            },
         {
             {102, 116},
             {111, 126},
@@ -658,7 +655,7 @@ std::vector<ItemPair> nfp_testdata = {
             {147, 84},
             {102, 84},
             {102, 116},
-        }
+            }
     },
     {
         {
@@ -674,7 +671,7 @@ std::vector<ItemPair> nfp_testdata = {
             {108, 70},
             {99, 102},
             {99, 122},
-        },
+            },
         {
             {107, 124},
             {128, 125},
@@ -691,7 +688,7 @@ std::vector<ItemPair> nfp_testdata = {
             {108, 85},
             {107, 86},
             {107, 124},
-        }
+            }
     },
     {
         {
@@ -706,7 +703,7 @@ std::vector<ItemPair> nfp_testdata = {
             {132, 57},
             {91, 98},
             {91, 100},
-        },
+            },
         {
             {101, 90},
             {103, 98},
@@ -724,74 +721,74 @@ std::vector<ItemPair> nfp_testdata = {
             {102, 87},
             {101, 89},
             {101, 90},
-        }
+            }
     }
 };
 
-std::vector<ItemPair> nfp_concave_testdata = {
-    { // ItemPair
-      {
-          {
-              {533726, 142141},
-              {532359, 143386},
-              {530141, 142155},
-              {528649, 160091},
-              {533659, 157607},
-              {538669, 160091},
-              {537178, 142155},
-              {534959, 143386},
-              {533726, 142141},
-          }
-      },
-      {
-          {
-              {118305, 11603},
-              {118311, 26616},
-              {113311, 26611},
-              {109311, 29604},
-              {109300, 44608},
-              {109311, 49631},
-              {113300, 52636},
-              {118311, 52636},
-              {118308, 103636},
-              {223830, 103636},
-              {236845, 90642},
-              {236832, 11630},
-              {232825, 11616},
-              {210149, 11616},
-              {211308, 13625},
-              {209315, 17080},
-              {205326, 17080},
-              {203334, 13629},
-              {204493, 11616},
-              {118305, 11603},
-          }
-      },
-    }
+    std::vector<ItemPair> nfp_concave_testdata = {
+        { // ItemPair
+         {
+             {
+                 {533726, 142141},
+                 {532359, 143386},
+                 {530141, 142155},
+                 {528649, 160091},
+                 {533659, 157607},
+                 {538669, 160091},
+                 {537178, 142155},
+                 {534959, 143386},
+                 {533726, 142141},
+                 }
+             },
+         {
+             {
+                 {118305, 11603},
+                 {118311, 26616},
+                 {113311, 26611},
+                 {109311, 29604},
+                 {109300, 44608},
+                 {109311, 49631},
+                 {113300, 52636},
+                 {118311, 52636},
+                 {118308, 103636},
+                 {223830, 103636},
+                 {236845, 90642},
+                 {236832, 11630},
+                 {232825, 11616},
+                 {210149, 11616},
+                 {211308, 13625},
+                 {209315, 17080},
+                 {205326, 17080},
+                 {203334, 13629},
+                 {204493, 11616},
+                 {118305, 11603},
+                 }
+             },
+         }
 };
 
 template<nfp::NfpLevel lvl, Coord SCALE>
 void testNfp(const std::vector<ItemPair>& testdata) {
     using namespace libnest2d;
-
+    
     Box bin(210*SCALE, 250*SCALE);
-
+    
     int testcase = 0;
-
+    
     auto& exportfun = exportSVG<SCALE, Box>;
-
+    
     auto onetest = [&](Item& orbiter, Item& stationary, unsigned /*testidx*/){
         testcase++;
-
+        
         orbiter.translate({210*SCALE, 0});
-
+        
         auto&& nfp = nfp::noFitPolygon<lvl>(stationary.rawShape(),
                                             orbiter.transformedShape());
-
+        
         placers::correctNfpPosition(nfp, stationary, orbiter);
-
+        
         auto valid = shapelike::isValid(nfp.first);
-
+        
         /*Item infp(nfp.first);
         if(!valid.first) {
             std::cout << "test instance: " << testidx << " "
@@ -799,46 +796,46 @@ void testNfp(const std::vector<ItemPair>& testdata) {
             std::vector<std::reference_wrapper<Item>> inp = {std::ref(infp)};
             exportfun(inp, bin, testidx);
         }*/
-
+        
         ASSERT_TRUE(valid.first);
-
+        
         Item infp(nfp.first);
-
+        
         int i = 0;
         auto rorbiter = orbiter.transformedShape();
         auto vo = nfp::referenceVertex(rorbiter);
-
+        
         ASSERT_TRUE(stationary.isInside(infp));
-
+        
         for(auto v : infp) {
             auto dx = getX(v) - getX(vo);
             auto dy = getY(v) - getY(vo);
-
+            
             Item tmp = orbiter;
-
+            
             tmp.translate({dx, dy});
-
+            
             bool touching = Item::touches(tmp, stationary);
-
+            
             if(!touching || !valid.first) {
                 std::vector<std::reference_wrapper<Item>> inp = {
                     std::ref(stationary), std::ref(tmp), std::ref(infp)
                 };
-
+                
                 exportfun(inp, bin, testcase*i++);
             }
-
+            
             ASSERT_TRUE(touching);
         }
     };
-
+    
     unsigned tidx = 0;
     for(auto& td : testdata) {
         auto orbiter = td.orbiter;
         auto stationary = td.stationary;
         onetest(orbiter, stationary, tidx++);
     }
-
+    
     tidx = 0;
     for(auto& td : testdata) {
         auto orbiter = td.stationary;
@@ -858,19 +855,19 @@ TEST(GeometryAlgorithms, nfpConvexConvex) {
 
 TEST(GeometryAlgorithms, pointOnPolygonContour) {
     using namespace libnest2d;
-
+    
     Rectangle input(10, 10);
-
+    
     placers::EdgeCache<PolygonImpl> ecache(input);
-
+    
     auto first = *input.begin();
     ASSERT_TRUE(getX(first) == getX(ecache.coords(0)));
     ASSERT_TRUE(getY(first) == getY(ecache.coords(0)));
-
+    
     auto last = *std::prev(input.end());
     ASSERT_TRUE(getX(last) == getX(ecache.coords(1.0)));
     ASSERT_TRUE(getY(last) == getY(ecache.coords(1.0)));
-
+    
     for(int i = 0; i <= 100; i++) {
         auto v = ecache.coords(i*(0.01));
         ASSERT_TRUE(shapelike::touches(v, input.transformedShape()));
@@ -879,24 +876,24 @@ TEST(GeometryAlgorithms, pointOnPolygonContour) {
 
 TEST(GeometryAlgorithms, mergePileWithPolygon) {
     using namespace libnest2d;
-
+    
     Rectangle rect1(10, 15);
     Rectangle rect2(15, 15);
     Rectangle rect3(20, 15);
-
+    
     rect2.translate({10, 0});
     rect3.translate({25, 0});
-
+    
     TMultiShape<PolygonImpl> pile;
     pile.push_back(rect1.transformedShape());
     pile.push_back(rect2.transformedShape());
-
+    
     auto result = nfp::merge(pile, rect3.transformedShape());
-
+    
     ASSERT_EQ(result.size(), 1);
-
+    
     Rectangle ref(45, 15);
-
+    
     ASSERT_EQ(shapelike::area(result.front()), ref.area());
 }
 
@@ -908,7 +905,7 @@ long double refMinAreaBox(const PolygonImpl& p) {
     
     long double min_area = std::numeric_limits<long double>::max();
     
- 
+    
     auto update_min = [&min_area, &it, &itx, &p]() {
         Segment s(*it, *itx);
         
@@ -935,67 +932,39 @@ template<class T> struct BoostGCD {
 };
 
 using Unit = int64_t;
-using Ratio = boost::rational<boost::multiprecision::int128_t>;// Rational<boost::multiprecision::int256_t>;
-
-//double gteMinAreaBox(const PolygonImpl& p) {    
-    
-//    using GteCoord = ClipperLib::cInt;
-//    using GtePoint = gte::Vector2<GteCoord>;
- 
-//    gte::MinimumAreaBox2<GteCoord, Ratio> mb;
-    
-//    std::vector<GtePoint> points; 
-//    points.reserve(p.Contour.size());
-    
-//    for(auto& pt : p.Contour) points.emplace_back(GtePoint{GteCoord(pt.X), GteCoord(pt.Y)});
-    
-//    mb(int(points.size()), points.data(), 0, nullptr, true);
-    
-//    auto min_area = double(mb.GetArea());
-    
-//    return min_area;
-//}
+using Ratio = boost::rational<boost::multiprecision::int128_t>;
 
 }
 
 TEST(RotatingCalipers, MinAreaBBCClk) {
-//    PolygonImpl poly({{-50, 30}, {-50, -50}, {50, -50}, {50, 50}, {-40, 50}});
-    
-//    PolygonImpl poly({{-50, 0}, {50, 0}, {0, 100}});
-    
     auto u = [](ClipperLib::cInt n) { return n*1000000; };
     PolygonImpl poly({ {u(0), u(0)}, {u(4), u(1)}, {u(2), u(4)}});
     
-    
     long double arearef = refMinAreaBox(poly);
     long double area = minAreaBoundingBox<PolygonImpl, Unit, Ratio>(poly).area();
-//    double gtearea = gteMinAreaBox(poly);
     
     ASSERT_LE(std::abs(area - arearef), 500e6 );
-//    ASSERT_LE(std::abs(gtearea - arearef), 500 );
-//    ASSERT_DOUBLE_EQ(gtearea, arearef);
 }
 
 TEST(RotatingCalipers, AllPrusaMinBB) {
-    size_t idx = 0;
+    //    /size_t idx = 0;
     long double err_epsilon = 500e6l;
     
     for(ClipperLib::Path rinput : PRINTER_PART_POLYGONS) {
-//        ClipperLib::Path rinput = PRINTER_PART_POLYGONS[idx];
-//        rinput.pop_back();
-//        std::reverse(rinput.begin(), rinput.end());
+        //        ClipperLib::Path rinput = PRINTER_PART_POLYGONS[idx];
+        //        rinput.pop_back();
+        //        std::reverse(rinput.begin(), rinput.end());
         
-//        PolygonImpl poly(removeCollinearPoints<PathImpl, PointImpl, Unit>(rinput, 1000000));
+        //        PolygonImpl poly(removeCollinearPoints<PathImpl, PointImpl, Unit>(rinput, 1000000));
         PolygonImpl poly(rinput);
         
         long double arearef = refMinAreaBox(poly);
         auto bb = minAreaBoundingBox<PathImpl, Unit, Ratio>(rinput);
         long double area = cast<long double>(bb.area());
-//        double area = gteMinAreaBox(poly);
         
         bool succ = std::abs(arearef - area) < err_epsilon;
-        std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " 
-                  << arearef << " actual: " << area << std::endl;
+        //        std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " 
+//                  << arearef << " actual: " << area << std::endl;
         
         ASSERT_TRUE(succ);
     }
@@ -1006,21 +975,20 @@ TEST(RotatingCalipers, AllPrusaMinBB) {
         
         PolygonImpl poly(removeCollinearPoints<PathImpl, PointImpl, Unit>(rinput, 1000000));
         
-        
         long double arearef = refMinAreaBox(poly);
         auto bb = minAreaBoundingBox<PolygonImpl, Unit, Ratio>(poly);
         long double area = cast<long double>(bb.area());
-//        double area = gteMinAreaBox(poly);
+        
         
         bool succ = std::abs(arearef - area) < err_epsilon;
-        std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " 
-                  << arearef << " actual: " << area << std::endl;
+        //        std::cout << idx++ << " " << (succ? "ok" : "failed") << " ref: " 
+//                  << arearef << " actual: " << area << std::endl;
         
         ASSERT_TRUE(succ);
     }
 }
 
 int main(int argc, char **argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
 }
diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp
index b261a79be..df248ca5d 100644
--- a/src/libslic3r/MTUtils.hpp
+++ b/src/libslic3r/MTUtils.hpp
@@ -7,6 +7,9 @@
 #include <utility>    // for std::forward
 #include <algorithm>
 
+#include "libslic3r.h"
+#include "Point.hpp"
+
 namespace Slic3r {
 
 /// Handy little spin mutex for the cached meshes.
@@ -248,6 +251,94 @@ template<class X, class Y> inline X ceil_i(X x, Y y)
     return (x % y) ? x / y + 1 : x / y;
 }
 
+// A shorter C++14 style form of the enable_if metafunction
+template<bool B, class T>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
+// /////////////////////////////////////////////////////////////////////////////
+// Type safe conversions to and from scaled and unscaled coordinates
+// /////////////////////////////////////////////////////////////////////////////
+
+// A meta-predicate which is true for integers wider than or equal to coord_t
+template<class I> struct is_scaled_coord
+{
+    static const SLIC3R_CONSTEXPR bool value =
+        std::is_integral<I>::value &&
+        std::numeric_limits<I>::digits >=
+            std::numeric_limits<coord_t>::digits;
+};
+
+// Meta predicates for floating, 'scaled coord' and generic arithmetic types
+template<class T>
+using FloatingOnly = enable_if_t<std::is_floating_point<T>::value, T>;
+
+template<class T>
+using ScaledCoordOnly = enable_if_t<is_scaled_coord<T>::value, T>;
+
+template<class T>
+using ArithmeticOnly = enable_if_t<std::is_arithmetic<T>::value, T>;
+
+// A shorter form for a generic Eigen vector which is widely used in PrusaSlicer 
+template<class T, int N>
+using EigenVec = Eigen::Matrix<T, N, 1, Eigen::DontAlign>;
+
+// Semantics are the following:
+// Upscaling (scaled()): only from floating point types (or Vec) to either
+//                       floating point or integer 'scaled coord' coordinates.
+// Downscaling (unscaled()): from arithmetic types (or Vec) to either
+//                           floating point only
+
+// Conversion definition from unscaled to floating point scaled
+template<class Tout,
+         class Tin,
+         class = FloatingOnly<Tin>,
+         class = FloatingOnly<Tout>>
+inline SLIC3R_CONSTEXPR Tout scaled(const Tin &v) SLIC3R_NOEXCEPT
+{
+    return static_cast<Tout>(v / static_cast<Tout>(SCALING_FACTOR));
+}
+
+// Conversion definition from unscaled to integer 'scaled coord'.
+// TODO: is the rounding necessary ? Here it is to show that it can be different
+// but it does not have to be. Using std::round means loosing noexcept and
+// constexpr modifiers
+template<class Tout = coord_t, class Tin, class = FloatingOnly<Tin>>
+inline SLIC3R_CONSTEXPR ScaledCoordOnly<Tout> scaled(const Tin &v) SLIC3R_NOEXCEPT
+{
+    //return static_cast<Tout>(std::round(v / SCALING_FACTOR));
+    return static_cast<Tout>(v / static_cast<Tout>(SCALING_FACTOR));
+}
+
+// Conversion for Eigen vectors (N dimensional points)
+template<class Tout = coord_t, class Tin, int N, class = FloatingOnly<Tin>>
+inline EigenVec<ArithmeticOnly<Tout>, N> scaled(const EigenVec<Tin, N> &v)
+{
+    return v.template cast<Tout>() / SCALING_FACTOR;
+}
+
+// Conversion from arithmetic scaled type to floating point unscaled
+template<class Tout = double,
+         class Tin,
+         class = ArithmeticOnly<Tin>,
+         class = FloatingOnly<Tout>>
+inline SLIC3R_CONSTEXPR Tout unscaled(const Tin &v) SLIC3R_NOEXCEPT
+{
+    return static_cast<Tout>(v * static_cast<Tout>(SCALING_FACTOR));
+}
+
+// Unscaling for Eigen vectors. Input base type can be arithmetic, output base
+// type can only be floating point.
+template<class Tout = double,
+         class Tin,
+         int N,
+         class = ArithmeticOnly<Tin>,
+         class = FloatingOnly<Tout>>
+inline SLIC3R_CONSTEXPR EigenVec<Tout, N> unscaled(
+    const EigenVec<Tin, N> &v) SLIC3R_NOEXCEPT
+{
+    return v.template cast<Tout>() * SCALING_FACTOR;
+}
+
 } // namespace Slic3r
 
 #endif // MTUTILS_HPP
diff --git a/src/libslic3r/MinAreaBoundingBox.cpp b/src/libslic3r/MinAreaBoundingBox.cpp
index 6fc1b3327..fafb54a58 100644
--- a/src/libslic3r/MinAreaBoundingBox.cpp
+++ b/src/libslic3r/MinAreaBoundingBox.cpp
@@ -39,7 +39,7 @@ template<> inline Slic3r::Points& contour(Slic3r::Polygon& sh) { return sh.point
 template<> inline const Slic3r::Points& contour(const Slic3r::Polygon& sh) { return sh.points; }
 
 template<> Slic3r::Points::iterator begin(Slic3r::Points& pts, const PathTag&) { return pts.begin();}
-template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.begin(); }
+template<> Slic3r::Points::const_iterator cbegin(const Slic3r::Points& pts, const PathTag&) { return pts.cbegin(); }
 template<> Slic3r::Points::iterator end(Slic3r::Points& pts, const PathTag&) { return pts.end();}
 template<> Slic3r::Points::const_iterator cend(const Slic3r::Points& pts, const PathTag&) { return pts.cend(); }
 
@@ -71,62 +71,67 @@ using Rational = boost::rational<__int128>;
 
 MinAreaBoundigBox::MinAreaBoundigBox(const Polygon &p, PolygonLevel pc)
 {
-    const Polygon& chull = pc == pcConvex ? p : libnest2d::sl::convexHull(p);
-    
-    libnest2d::RotatedBox<Point, Unit> box = 
-            libnest2d::minAreaBoundingBox<Polygon, Unit, Rational>(chull);
-    
-    m_right = box.right_extent();
-    m_bottom = box.bottom_extent();
-    m_axis = box.axis();
+    const Polygon &chull = pc == pcConvex ? p :
+                                            libnest2d::sl::convexHull(p);
+
+    libnest2d::RotatedBox<Point, Unit> box =
+        libnest2d::minAreaBoundingBox<Polygon, Unit, Rational>(chull);
+
+    m_right  = libnest2d::cast<long double>(box.right_extent());
+    m_bottom = libnest2d::cast<long double>(box.bottom_extent());
+    m_axis   = box.axis();
 }
 
 MinAreaBoundigBox::MinAreaBoundigBox(const ExPolygon &p, PolygonLevel pc)
 {
-    const ExPolygon& chull = pc == pcConvex ? p : libnest2d::sl::convexHull(p);
-    
-    libnest2d::RotatedBox<Point, Unit> box = 
-            libnest2d::minAreaBoundingBox<ExPolygon, Unit, Rational>(chull);
-    
-    m_right = box.right_extent();
-    m_bottom = box.bottom_extent();
-    m_axis = box.axis();
+    const ExPolygon &chull = pc == pcConvex ? p :
+                                              libnest2d::sl::convexHull(p);
+
+    libnest2d::RotatedBox<Point, Unit> box =
+        libnest2d::minAreaBoundingBox<ExPolygon, Unit, Rational>(chull);
+
+    m_right  = libnest2d::cast<long double>(box.right_extent());
+    m_bottom = libnest2d::cast<long double>(box.bottom_extent());
+    m_axis   = box.axis();
 }
 
 MinAreaBoundigBox::MinAreaBoundigBox(const Points &pts, PolygonLevel pc)
 {
-    const Points& chull = pc == pcConvex ? pts : libnest2d::sl::convexHull(pts);
-    
-    libnest2d::RotatedBox<Point, Unit> box = 
-            libnest2d::minAreaBoundingBox<Points, Unit, Rational>(chull);
-    
-    m_right = box.right_extent();
-    m_bottom = box.bottom_extent();
-    m_axis = box.axis();
+    const Points &chull = pc == pcConvex ? pts :
+                                           libnest2d::sl::convexHull(pts);
+
+    libnest2d::RotatedBox<Point, Unit> box =
+        libnest2d::minAreaBoundingBox<Points, Unit, Rational>(chull);
+
+    m_right  = libnest2d::cast<long double>(box.right_extent());
+    m_bottom = libnest2d::cast<long double>(box.bottom_extent());
+    m_axis   = box.axis();
 }
 
 double MinAreaBoundigBox::angle_to_X() const
 {
     double ret = std::atan2(m_axis.y(), m_axis.x());
-    auto s = std::signbit(ret);
-    if(s) ret += 2 * PI;
+    auto   s   = std::signbit(ret);
+    if (s) ret += 2 * PI;
     return -ret;
 }
 
 long double MinAreaBoundigBox::width() const
 {
-    return std::abs(m_bottom) / std::sqrt(libnest2d::pl::magnsq<Point, long double>(m_axis));
+    return std::abs(m_bottom) /
+           std::sqrt(libnest2d::pl::magnsq<Point, long double>(m_axis));
 }
 
 long double MinAreaBoundigBox::height() const
 {
-    return std::abs(m_right) / std::sqrt(libnest2d::pl::magnsq<Point, long double>(m_axis));
+    return std::abs(m_right) /
+           std::sqrt(libnest2d::pl::magnsq<Point, long double>(m_axis));
 }
 
 long double MinAreaBoundigBox::area() const
 {
     long double asq = libnest2d::pl::magnsq<Point, long double>(m_axis);
-    return m_bottom * m_right / asq;   
+    return m_bottom * m_right / asq;
 }
 
 void remove_collinear_points(Polygon &p)
@@ -138,5 +143,4 @@ void remove_collinear_points(ExPolygon &p)
 {
     p = libnest2d::removeCollinearPoints<ExPolygon>(p, Unit(0));
 }
-
-}
+} // namespace Slic3r
diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp
index 36f7e3971..bc0f933d1 100644
--- a/src/libslic3r/ModelArrange.cpp
+++ b/src/libslic3r/ModelArrange.cpp
@@ -610,7 +610,7 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model,
                 
                 if(tolerance > EPSILON) {
                     Polygons pp { p };
-                    pp = p.simplify(double(scaled(tolerance)));
+                    pp = p.simplify(scaled<double>(tolerance));
                     if (!pp.empty()) p = pp.front();
                 }
                 
diff --git a/src/libslic3r/SLA/SLABasePool.cpp b/src/libslic3r/SLA/SLABasePool.cpp
index 3b199c4eb..04cbd7824 100644
--- a/src/libslic3r/SLA/SLABasePool.cpp
+++ b/src/libslic3r/SLA/SLABasePool.cpp
@@ -5,6 +5,7 @@
 #include "SLABoostAdapter.hpp"
 #include "ClipperUtils.hpp"
 #include "Tesselate.hpp"
+#include "MTUtils.hpp"
 
 // For debugging:
 //#include <fstream>
@@ -203,7 +204,7 @@ void offset(ExPolygon& sh, coord_t distance) {
     }
 
     ClipperOffset offs;
-    offs.ArcTolerance = 0.01*scaled(1.0);
+    offs.ArcTolerance = scaled<double>(0.01);
     Paths result;
     offs.AddPath(ctour, jtRound, etClosedPolygon);
     offs.AddPaths(holes, jtRound, etClosedPolygon);
@@ -351,7 +352,7 @@ Contour3D round_edges(const ExPolygon& base_plate,
         double x2 = xx*xx;
         double stepy = std::sqrt(r2 - x2);
 
-        offset(ob, s*scaled(xx));
+        offset(ob, s * scaled(xx));
         wh = ceilheight_mm - radius_mm + stepy;
 
         Contour3D pwalls;
@@ -375,7 +376,7 @@ Contour3D round_edges(const ExPolygon& base_plate,
             double xx = radius_mm - i*stepx;
             double x2 = xx*xx;
             double stepy = std::sqrt(r2 - x2);
-            offset(ob, s*scaled(xx));
+            offset(ob, s * scaled(xx));
             wh = ceilheight_mm - radius_mm - stepy;
 
             Contour3D pwalls;
@@ -476,7 +477,7 @@ ExPolygons concave_hull(const ExPolygons& polys, double max_dist_mm = 50,
         double dx = x(c) - x(cc), dy = y(c) - y(cc);
         double l = std::sqrt(dx * dx + dy * dy);
         double nx = dx / l, ny = dy / l;
-        double max_dist = scaled(max_dist_mm);
+        double max_dist = scaled<double>(max_dist_mm);
 
         ExPolygon& expo = punion[idx++];
         BoundingBox querybb(expo);
@@ -492,7 +493,7 @@ ExPolygons concave_hull(const ExPolygons& polys, double max_dist_mm = 50,
         ctour.reserve(3);
         ctour.emplace_back(cc);
 
-        Point d(coord_t(scaled(1.)*nx), coord_t(scaled(1.)*ny));
+        Point d(scaled(nx), scaled(ny));
         ctour.emplace_back(c + Point( -y(d),  x(d) ));
         ctour.emplace_back(c + Point(  y(d), -x(d) ));
         offset(r, scaled(1.));
@@ -529,14 +530,14 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h,
     ExPolygons tmp; tmp.reserve(count);
     for(ExPolygons& o : out)
         for(ExPolygon& e : o) {
-            auto&& exss = e.simplify(scaled(0.1));
+            auto&& exss = e.simplify(scaled<double>(0.1));
             for(ExPolygon& ep : exss) tmp.emplace_back(std::move(ep));
         }
 
     ExPolygons utmp = unify(tmp);
 
     for(auto& o : utmp) {
-        auto&& smp = o.simplify(scaled(0.1));
+        auto&& smp = o.simplify(scaled<double>(0.1));
         output.insert(output.end(), smp.begin(), smp.end());
     }
 }
diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp
index c73ae5650..7ae481ffb 100644
--- a/src/libslic3r/SLAPrint.cpp
+++ b/src/libslic3r/SLAPrint.cpp
@@ -668,7 +668,7 @@ void SLAPrint::process()
     double ilhd = m_material_config.initial_layer_height.getFloat();
     auto   ilh  = float(ilhd);
 
-    auto ilhs = scaled(ilhd);
+    coord_t      ilhs     = scaled(ilhd);
     const size_t objcount = m_objects.size();
 
     static const unsigned min_objstatus = 0;   // where the per object operations start
@@ -694,17 +694,15 @@ void SLAPrint::process()
 
         // We need to prepare the slice index...
 
-        double lhd  = m_objects.front()->m_config.layer_height.getFloat();
-        float  lh   = float(lhd);
-        auto   lhs  = scaled(lhd);
-
-        auto &&bb3d  = mesh.bounding_box();
-        double minZ  = bb3d.min(Z) - po.get_elevation();
-        double maxZ  = bb3d.max(Z);
-        auto   minZf = float(minZ);
-
-        auto minZs = scaled(minZ);
-        auto maxZs = scaled(maxZ);
+        double  lhd  = m_objects.front()->m_config.layer_height.getFloat();
+        float   lh   = float(lhd);
+        coord_t lhs  = scaled(lhd);
+        auto && bb3d = mesh.bounding_box();
+        double  minZ = bb3d.min(Z) - po.get_elevation();
+        double  maxZ = bb3d.max(Z);
+        auto    minZf = float(minZ);
+        coord_t minZs = scaled(minZ);
+        coord_t maxZs = scaled(maxZ);
 
         po.m_slice_index.clear();
         
@@ -1013,9 +1011,6 @@ void SLAPrint::process()
         using ClipperPolygons = std::vector<ClipperPolygon>;
         namespace sl = libnest2d::shapelike;    // For algorithms
 
-        // If the raster has vertical orientation, we will flip the coordinates
-//        bool flpXY = m_printer_config.display_orientation.getInt() == SLADisplayOrientation::sladoPortrait;
-
         // Set up custom union and diff functions for clipper polygons
         auto polyunion = [] (const ClipperPolygons& subjects)
         {
@@ -1066,8 +1061,8 @@ void SLAPrint::process()
 
         const int    fade_layers_cnt    = m_default_object_config.faded_layers.getInt();// 10 // [3;20]
 
-        const double width              = scaled(m_printer_config.display_width.getFloat());
-        const double height             = scaled(m_printer_config.display_height.getFloat());
+        const auto width                = scaled<double>(m_printer_config.display_width.getFloat());
+        const auto height               = scaled<double>(m_printer_config.display_height.getFloat());
         const double display_area       = width*height;
 
         // get polygons for all instances in the object
@@ -1123,11 +1118,6 @@ void SLAPrint::process()
                     sl::translate(poly, ClipperPoint{instances[i].shift(X),
                                                      instances[i].shift(Y)});
 
-//                    if (flpXY) {
-//                        for(auto& p : poly.Contour) std::swap(p.X, p.Y);
-//                        for(auto& h : poly.Holes) for(auto& p : h) std::swap(p.X, p.Y);
-//                    }
-
                     polygons.emplace_back(std::move(poly));
                 }
             }
diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h
index 8cafae17c..dc2b6a4ec 100644
--- a/src/libslic3r/libslic3r.h
+++ b/src/libslic3r/libslic3r.h
@@ -61,20 +61,6 @@ typedef double  coordf_t;
 #define SLIC3R_NOEXCEPT  noexcept
 #endif
 
-template<class Tf> inline SLIC3R_CONSTEXPR coord_t scaled(Tf val)
-{
-    static_assert (std::is_floating_point<Tf>::value, "Floating point only");
-    return coord_t(val / Tf(SCALING_FACTOR));
-}
-
-template<class Tf = double> inline SLIC3R_CONSTEXPR Tf unscaled(coord_t val)
-{
-    static_assert (std::is_floating_point<Tf>::value, "Floating point only");
-    return Tf(val * Tf(SCALING_FACTOR));
-}
-
-inline SLIC3R_CONSTEXPR float unscaledf(coord_t val) { return unscaled<float>(val); }
-
 inline std::string debug_out_path(const char *name, ...)
 {
 	char buffer[2048];

From 6ff434aba3367e2111b1ff809ea744ca39347a56 Mon Sep 17 00:00:00 2001
From: tamasmeszaros <meszaros.q@gmail.com>
Date: Wed, 26 Jun 2019 11:10:41 +0200
Subject: [PATCH 2/2] Fixes some ModelArrange warnings

---
 src/libslic3r/MTUtils.hpp      |  9 ---------
 src/libslic3r/ModelArrange.cpp | 18 ++++++++++--------
 2 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp
index df248ca5d..70603cd15 100644
--- a/src/libslic3r/MTUtils.hpp
+++ b/src/libslic3r/MTUtils.hpp
@@ -242,15 +242,6 @@ template<class C> bool all_of(const C &container)
                        });
 }
 
-template<class X, class Y> inline X ceil_i(X x, Y y)
-{
-    static_assert(std::is_integral<X>::value &&
-                      std::is_integral<Y>::value && sizeof(X) >= sizeof(Y),
-                  "");
-
-    return (x % y) ? x / y + 1 : x / y;
-}
-
 // A shorter C++14 style form of the enable_if metafunction
 template<bool B, class T>
 using enable_if_t = typename std::enable_if<B, T>::type;
diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp
index bc0f933d1..db36653b0 100644
--- a/src/libslic3r/ModelArrange.cpp
+++ b/src/libslic3r/ModelArrange.cpp
@@ -62,10 +62,10 @@ std::string toString(const Model& model, bool holes = true) {
             objinst->transform_mesh(&tmpmesh);
             ExPolygons expolys = tmpmesh.horizontal_projection();
             for(auto& expoly_complex : expolys) {
-
-                auto tmp = expoly_complex.simplify(1.0/SCALING_FACTOR);
+                
+                ExPolygons tmp = expoly_complex.simplify(scaled<double>(1.));
                 if(tmp.empty()) continue;
-                auto expoly = tmp.front();
+                ExPolygon expoly = tmp.front();
                 expoly.contour.make_clockwise();
                 for(auto& h : expoly.holes) h.make_counter_clockwise();
 
@@ -633,8 +633,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model,
                 if(item.vertexCount() > 3) {
                     item.rotation(Geometry::rotation_diff_z(rotation0, objinst->get_rotation()));
                     item.translation({
-                    ClipperLib::cInt(objinst->get_offset(X)/SCALING_FACTOR),
-                    ClipperLib::cInt(objinst->get_offset(Y)/SCALING_FACTOR)
+                        scaled<ClipperLib::cInt>(objinst->get_offset(X)),
+                        scaled<ClipperLib::cInt>(objinst->get_offset(Y))
                     });
                     ret.emplace_back(objinst, item);
                 }
@@ -658,8 +658,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model,
         Item item(std::move(pn));
         item.rotation(wti.rotation),
         item.translation({
-        ClipperLib::cInt(wti.pos(0)/SCALING_FACTOR),
-        ClipperLib::cInt(wti.pos(1)/SCALING_FACTOR)
+            scaled<ClipperLib::cInt>(wti.pos(0)),
+            scaled<ClipperLib::cInt>(wti.pos(1))
         });
         ret.emplace_back(nullptr, item);
     }
@@ -822,7 +822,9 @@ bool arrange(Model &model,              // The model with the geometries
 
     auto& cfn = stopcondition;
     
-    coord_t md = ceil_i(min_obj_distance, 2) - SCALED_EPSILON;
+    // Integer ceiling the min distance from the bed perimeters
+    coord_t md = min_obj_distance - SCALED_EPSILON;
+    md = (md % 2) ? md / 2 + 1 : md / 2;
 
     auto binbb = Box({libnest2d::Coord{bbb.min(0)} - md,
                       libnest2d::Coord{bbb.min(1)} - md},