From 530148575b06fbf423166ced0d57c7b9eeca1dd4 Mon Sep 17 00:00:00 2001
From: Vojtech Bubnik <bubnikv@gmail.com>
Date: Mon, 14 Dec 2020 12:36:55 +0100
Subject: [PATCH] Avoid crossing perimeters max detour could newly be specified
 in percentage of the direct path.

---
 src/libslic3r/GCode/AvoidCrossingPerimeters.cpp | 13 ++++++++++---
 src/libslic3r/PrintConfig.cpp                   |  5 +++--
 src/libslic3r/PrintConfig.hpp                   |  2 +-
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
index 8262c3857..8758450c1 100644
--- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
+++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
@@ -903,9 +903,16 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
         travel_intersection_count = 0;
     }
 
-    double max_detour_length scale_(gcodegen.config().avoid_crossing_perimeters_max_detour);
-    if (max_detour_length > 0 && (result_pl.length() - travel.length()) > max_detour_length)
-        result_pl = {start, end};
+    ConfigOptionFloatOrPercent &opt_max_detour = gcodegen.config().avoid_crossing_perimeters_max_detour;
+    if (opt_max_detour.value > 0) {
+        double direct_length     = travel.length();
+        double detour            = result_pl.length() - direct_length;
+        double max_detour_length = opt_max_detour.percent ?
+            direct_length * 0.01 * opt_max_detour.value :
+            scale_(opt_max_detour.value);
+        if (detour > max_detour_length)
+            result_pl = {start, end};
+    }
 
     if (use_external) {
         result_pl.translate(-scaled_origin);
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 2fa30cc24..8b6f7b34c 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -188,11 +188,12 @@ void PrintConfigDef::init_fff_params()
     def->label = L("Avoid crossing perimeters - Max detour length");
     def->category = L("Layers and Perimeters");
     def->tooltip = L("The maximum detour length for avoid crossing perimeters. "
-                     "If the detour is longer than this value, avoid crossing perimeters is not applied for this path.");
+                     "If the detour is longer than this value, avoid crossing perimeters is not applied for this travel path. "
+                     "Detour length could be specified either as an absolute value or as percentage (for example 50%) of a direct travel path.");
     def->sidetext = L("mm (zero to disable)");
     def->min = 0;
     def->mode = comExpert;
-    def->set_default_value(new ConfigOptionFloat(0.));
+    def->set_default_value(new ConfigOptionFloatOrPercent(0.));
 
     def = this->add("bed_temperature", coInts);
     def->label = L("Other layers");
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index f30d2e875..b5896891e 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -828,7 +828,7 @@ class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig
 public:
 
     ConfigOptionBool                avoid_crossing_perimeters;
-    ConfigOptionFloat               avoid_crossing_perimeters_max_detour;
+    ConfigOptionFloatOrPercent      avoid_crossing_perimeters_max_detour;
     ConfigOptionPoints              bed_shape;
     ConfigOptionInts                bed_temperature;
     ConfigOptionFloat               bridge_acceleration;