Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsupermerill <merill@free.fr>2022-08-05 03:27:23 +0300
committersupermerill <merill@free.fr>2022-08-05 03:27:23 +0300
commit3b62b1979ffce95632597e7af7c1c554948aaf8f (patch)
tree8c16db7b723af3427c6155986f0be052677b7666
parent572e3f970e78febddb73808eaa6c4a013ae5eed4 (diff)
parent373dd2658459a8be2118a2eb97994fa66c9347fc (diff)
Fix arachne issues and some others
-rw-r--r--src/libslic3r/Arachne/utils/ExtrusionLine.cpp12
-rw-r--r--src/libslic3r/Arachne/utils/ExtrusionLine.hpp1
-rw-r--r--src/libslic3r/ClipperUtils.cpp169
-rw-r--r--src/libslic3r/ClipperUtils.hpp2
-rw-r--r--src/libslic3r/Flow.cpp12
-rw-r--r--src/libslic3r/GCode.cpp2
-rw-r--r--src/libslic3r/GCode/SeamPlacer.cpp13
-rw-r--r--src/libslic3r/PerimeterGenerator.cpp149
-rw-r--r--src/libslic3r/ShortestPath.cpp7
-rw-r--r--src/slic3r/GUI/3DBed.cpp2
-rw-r--r--src/slic3r/GUI/FreeCADDialog.cpp2
11 files changed, 257 insertions, 114 deletions
diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp
index 69f235853..426f9064d 100644
--- a/src/libslic3r/Arachne/utils/ExtrusionLine.cpp
+++ b/src/libslic3r/Arachne/utils/ExtrusionLine.cpp
@@ -28,6 +28,18 @@ int64_t ExtrusionLine::getLength() const
return len;
}
+bool ExtrusionLine::isZeroLength() const
+{
+ if (junctions.empty())
+ return true;
+ ExtrusionJunction prev = junctions.front();
+ for (const ExtrusionJunction& next : junctions) {
+ if ((next.p - prev.p).cast<int64_t>().squaredNorm() > SCALED_EPSILON)
+ return false;
+ }
+ return true;
+}
+
coord_t ExtrusionLine::getMinimalWidth() const
{
return std::min_element(junctions.cbegin(), junctions.cend(),
diff --git a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp
index 776a175b6..d7c4d6b14 100644
--- a/src/libslic3r/Arachne/utils/ExtrusionLine.hpp
+++ b/src/libslic3r/Arachne/utils/ExtrusionLine.hpp
@@ -119,6 +119,7 @@ struct ExtrusionLine
* Sum the total length of this path.
*/
int64_t getLength() const;
+ bool isZeroLength() const;
int64_t polylineLength() const { return getLength(); }
/*!
diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp
index 6b0c95c1f..1faa5f6c3 100644
--- a/src/libslic3r/ClipperUtils.cpp
+++ b/src/libslic3r/ClipperUtils.cpp
@@ -755,7 +755,7 @@ Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subje
//perform y safing : if a line is on the same Y, clipper may not pick the good point.
//note: if not enough, next time, add some of the X coordinate (modulo it so it's contained in the scaling part)
- for (ClipperLib::Paths* input : { &input_subject, &input_clip })
+ for (ClipperLib::Paths* input : { &input_subject, &input_clip }) {
for (ClipperLib::Path& path : *input) {
coord_t lasty = 0;
for (ClipperLib::IntPoint& pt : path) {
@@ -765,6 +765,7 @@ Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subje
lasty = pt.y();
}
}
+ }
// init Clipper
ClipperLib::Clipper clipper;
@@ -809,6 +810,172 @@ Polylines _clipper_pl_open(ClipperLib::ClipType clipType, PathsProvider1 &&subje
return PolyTreeToPolylines(std::move(retval));
}
+void scaleClipperPolygons(ClipperLib_Z::Paths& polygons)
+{
+ CLIPPERUTILS_PROFILE_FUNC();
+ for (ClipperLib_Z::Paths::iterator it = polygons.begin(); it != polygons.end(); ++it)
+ for (ClipperLib_Z::Path::iterator pit = (*it).begin(); pit != (*it).end(); ++pit) {
+ pit->x() <<= CLIPPER_OFFSET_POWER_OF_2;
+ pit->y() <<= CLIPPER_OFFSET_POWER_OF_2;
+ pit->z() <<= CLIPPER_OFFSET_POWER_OF_2;
+ }
+}
+ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Paths& subjects, const ClipperLib_Z::Paths& clip, ClipperLib_Z::ClipType clipType)
+{
+ ClipperLib_Z::Clipper clipper;
+ clipper.ZFillFunction([](const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, const ClipperLib_Z::IntPoint& e2bot,
+ const ClipperLib_Z::IntPoint& e2top, ClipperLib_Z::IntPoint& pt) {
+ ClipperLib_Z::IntPoint start = e1bot;
+ ClipperLib_Z::IntPoint end = e1top;
+
+ if (start.z() <= 0 && end.z() <= 0) {
+ start = e2bot;
+ end = e2top;
+ }
+
+ assert(start.z() > 0 && end.z() > 0);
+
+ // Interpolate extrusion line width.
+ double length_sqr = (end - start).cast<double>().squaredNorm();
+ double dist_sqr = (pt - start).cast<double>().squaredNorm();
+ double t = std::sqrt(dist_sqr / length_sqr);
+
+ pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
+ });
+
+ //TODO: //scale to have some more precision to do some Y-bugfix like in _clipper_pl_open
+
+ // read input
+ ClipperLib_Z::Paths input_subject;
+ for (const ClipperLib_Z::Path& pg : subjects)
+ input_subject.push_back(pg);
+ ClipperLib_Z::Paths input_clip;
+ for (const ClipperLib_Z::Path& pg : clip)
+ input_clip.push_back(pg);
+
+ //scale to have some more precision to do some Y-bugfix
+ scaleClipperPolygons(input_subject);
+ scaleClipperPolygons(input_clip);
+
+ //perform y safing : if a line is on the same Y, clipper may not pick the good point.
+ //note: if not enough, next time, add some of the X coordinate (modulo it so it's contained in the scaling part)
+ for (ClipperLib_Z::Paths* input : { &input_subject, &input_clip }) {
+ for (ClipperLib_Z::Path& path : *input) {
+ coord_t lasty = 0;
+ for (ClipperLib_Z::IntPoint& pt : path) {
+ if (lasty == pt.y()) {
+ pt.y() += 2048;// well below CLIPPER_OFFSET_POWER_OF_2, need also to be high enough that it won't be reduce to 0 if cut near an end
+ }
+ lasty = pt.y();
+ }
+ }
+ }
+
+ clipper.AddPaths(input_subject, ClipperLib_Z::ptSubject, false);
+ clipper.AddPaths(input_clip, ClipperLib_Z::ptClip, true);
+
+ ClipperLib_Z::PolyTree clipped_polytree;
+ ClipperLib_Z::Paths clipped_paths;
+ clipper.Execute(clipType, clipped_polytree, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero);
+
+
+ //restore good y
+ std::vector<ClipperLib_Z::PolyNode*> to_check;
+ to_check.push_back(&clipped_polytree);
+ while (!to_check.empty()) {
+ ClipperLib_Z::PolyNode* node = to_check.back();
+ to_check.pop_back();
+ for (ClipperLib_Z::IntPoint& pit : node->Contour) {
+ pit.x() += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
+ pit.y() += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
+ pit.z() += CLIPPER_OFFSET_SCALE_ROUNDING_DELTA;
+ pit.x() >>= CLIPPER_OFFSET_POWER_OF_2;
+ pit.y() >>= CLIPPER_OFFSET_POWER_OF_2;
+ pit.z() >>= CLIPPER_OFFSET_POWER_OF_2;
+ }
+ //note: moving in Y may create 0-length segment, so it needs an extra post-processing step to remove these duplicate points.
+ for (size_t idx = 1; idx < node->Contour.size(); ++idx) {
+ ClipperLib_Z::IntPoint& pit = node->Contour[idx];
+ ClipperLib_Z::IntPoint& previous = node->Contour[idx - 1];
+ // unscaling remove too small differences. The equality is enough.
+ if (pit.x() == previous.x() && pit.y() == previous.y()) {
+ node->Contour.erase(node->Contour.begin() + idx);
+ --idx;
+ }
+ }
+ //be sure you don't save 1-point paths
+ if (node->Contour.size() == 1)
+ node->Contour.clear();
+ to_check.insert(to_check.end(), node->Childs.begin(), node->Childs.end());
+ }
+
+ ClipperLib_Z::PolyTreeToPaths(clipped_polytree, clipped_paths);
+
+ //can contain 0-length segments
+ for (ClipperLib_Z::Path& path : clipped_paths) {
+ for (size_t i = 1; i < path.size(); i++) {
+ if ((path[i - 1] - path[i]).squaredNorm() < SCALED_EPSILON) {
+ path.erase(path.begin() + i);
+ i--;
+ }
+ }
+ }
+
+ // Clipped path could contain vertices from the clip with a Z coordinate equal to zero.
+ // For those vertices, we must assign value based on the subject.
+ // This happens only in sporadic cases.
+ for (ClipperLib_Z::Path& path : clipped_paths)
+ for (ClipperLib_Z::IntPoint& c_pt : path)
+ if (c_pt.z() == 0) {
+ const Point pt(c_pt.x(), c_pt.y());
+ Point projected_pt_min;
+ const ClipperLib_Z::IntPoint* it_a = nullptr;
+ const ClipperLib_Z::IntPoint* it_b = nullptr;
+ auto dist_sqr_min = std::numeric_limits<double>::max();
+ Point prev(0, 0);
+ for (const ClipperLib_Z::Path& subject : subjects) {
+ // Now we must find the corresponding line on with this point is located and compute line width (Z coordinate).
+ if (subject.size() <= 2)
+ continue;
+
+ for (auto it = std::next(subject.begin()); it != subject.end(); ++it) {
+ Point curr(it->x(), it->y());
+ if (it_a == nullptr) {
+ assert(std::prev(it) == subject.begin());
+ prev = Point(subject.front().x(), subject.front().y());
+ }
+ Point projected_pt = pt.projection_onto(Line(prev, curr));
+ if (double dist_sqr = (projected_pt - pt).cast<double>().squaredNorm(); dist_sqr < dist_sqr_min) {
+ dist_sqr_min = dist_sqr;
+ projected_pt_min = projected_pt;
+ it_a = &*std::prev(it);
+ it_b = &*it;
+ }
+ prev = curr;
+ }
+
+ assert(dist_sqr_min <= SCALED_EPSILON);
+ assert(*it_a != subject.back());
+ }
+
+ const Point pt_a(it_a->x(), it_a->y());
+ const Point pt_b(it_b->x(), it_b->y());
+ const double line_len = (pt_b - pt_a).cast<double>().norm();
+ const double dist = (projected_pt_min - pt_a).cast<double>().norm();
+ c_pt.z() = coord_t(double(it_a->z()) + (dist / line_len) * double(it_b->z() - it_a->z()));
+ }
+ assert([&clipped_paths = std::as_const(clipped_paths)]() -> bool {
+ for (const ClipperLib_Z::Path& path : clipped_paths)
+ for (const ClipperLib_Z::IntPoint& pt : path)
+ if (pt.z() <= 0)
+ return false;
+ return true;
+ }());
+
+ return clipped_paths;
+}
+
+
// If the split_at_first_point() call above happens to split the polygon inside the clipping area
// we would get two consecutive polylines instead of a single one, so we go through them in order
// to recombine continuous polylines.
diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp
index 069ddd1ba..35109821c 100644
--- a/src/libslic3r/ClipperUtils.hpp
+++ b/src/libslic3r/ClipperUtils.hpp
@@ -3,6 +3,7 @@
#include "libslic3r.h"
#include "clipper.hpp"
+#include "clipper/clipper_z.hpp"
#include "ExPolygon.hpp"
#include "Polygon.hpp"
#include "Surface.hpp"
@@ -405,6 +406,7 @@ Slic3r::Polylines diff_pl(const Slic3r::Polyline &subject, const Slic3r::ExPoly
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygon &clip);
Slic3r::Polylines diff_pl(const Slic3r::Polylines &subject, const Slic3r::ExPolygons &clip);
Slic3r::Polylines diff_pl(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip);
+ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Paths& subjects, const ClipperLib_Z::Paths& clip, ClipperLib_Z::ClipType clipType);
inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygons &clip)
{
diff --git a/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp
index 888f678f8..9bfa2d519 100644
--- a/src/libslic3r/Flow.cpp
+++ b/src/libslic3r/Flow.cpp
@@ -430,6 +430,9 @@ Flow support_material_flow(const PrintObject* object, float layer_height)
layer_height = object->config().support_material_layer_height.get_abs_value(nzd);
if (layer_height == 0) {
layer_height = object->print()->config().max_layer_height.get_abs_value(extruder_id, nzd);
+ if (layer_height == 0) {
+ layer_height = nzd * 0.75;
+ }
}
}
layer_height = std::min(layer_height, max_height);
@@ -489,6 +492,9 @@ Flow support_material_interface_flow(const PrintObject* object, float layer_heig
layer_height = object->config().support_material_interface_layer_height.get_abs_value(nzd);
if (layer_height == 0) {
layer_height = object->print()->config().max_layer_height.get_abs_value(extruder_id, nzd);
+ if (layer_height == 0) {
+ layer_height = nzd * 0.75;
+ }
}
}
layer_height = std::min(layer_height, max_height);
@@ -524,6 +530,9 @@ Flow raft_flow(const PrintObject* object, float layer_height)
layer_height = object->config().raft_interface_layer_height.get_abs_value(nzd);
if (layer_height == 0) {
layer_height = object->print()->config().max_layer_height.get_abs_value(extruder_id, nzd);
+ if (layer_height == 0) {
+ layer_height = nzd * 0.75;
+ }
}
}
layer_height = std::min(layer_height, max_height);
@@ -559,6 +568,9 @@ Flow raft_interface_flow(const PrintObject* object, float layer_height)
layer_height = object->config().raft_interface_layer_height.get_abs_value(nzd);
if (layer_height == 0) {
layer_height = object->print()->config().max_layer_height.get_abs_value(extruder_id, nzd);
+ if (layer_height == 0) {
+ layer_height = nzd * 0.75;
+ }
}
}
layer_height = std::min(layer_height, max_height);
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 07a5a7150..33a189291 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -4039,7 +4039,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
current_pos = pt_inside.cast<double>();
//go to the inside (use clipper for easy shift)
Polygon original_polygon = original_loop.polygon();
- Polygons polys = offset(original_polygon, (original_polygon.is_clockwise()?1:-1) * dist);
+ Polygons polys = offset(original_polygon, -dist);
//find nearest point
size_t best_poly_idx = 0;
size_t best_pt_idx = 0;
diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp
index 83751a3c2..09259d041 100644
--- a/src/libslic3r/GCode/SeamPlacer.cpp
+++ b/src/libslic3r/GCode/SeamPlacer.cpp
@@ -792,13 +792,24 @@ Point SeamPlacer::calculate_seam(const Layer& layer, SeamPosition seam_position,
if (saw_custom)
last_pos = candidate;
}
- if(!saw_custom)
+ if (!saw_custom) {
if (external_perimeters_first || (loop.loop_role() & ExtrusionLoopRole::elrFirstLoop) != 0) {
// this is if external_perimeters_first
// this is if only space for one externalperimeter.
//in these case, there isn't a seam from the inner loops, so we had to creat our on
last_pos = this->get_random_seam(layer_idx, polygon, po_idx);
+ } else if (po != nullptr) {
+ //just in case, do random if it's on top of a previous one
+ Point aligned_last_pos;
+ std::optional<Point> pos = m_seam_history.get_last_seam(m_po_list[po_idx], layer_po->print_z, loop.polygon().bounding_box());
+ if (pos.has_value()) {
+ aligned_last_pos = *pos;
+ }
+ if (aligned_last_pos.distance_to(last_pos) < std::max(coord_t(polygon.length() / 100), nozzle_r*5) ){
+ last_pos = this->get_random_seam(layer_idx, polygon, po_idx);
+ }
}
+ }
} else if (loop.role() == erThinWall) {
//thin wall loop is like an external perimeter, but without anything near it.
last_pos = this->get_random_seam(layer_idx, polygon, po_idx);
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index 502622463..de76437d6 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -5,7 +5,6 @@
#include "ExtrusionEntityCollection.hpp"
#include "Geometry.hpp"
#include "ShortestPath.hpp"
-#include "clipper/clipper_z.hpp"
#include "Arachne/WallToolPaths.hpp"
#include "Arachne/utils/ExtrusionLine.hpp"
@@ -126,91 +125,6 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
ext_lines.junctions = std::move(out);
}
-static ClipperLib_Z::Paths clip_extrusion(const ClipperLib_Z::Paths &subjects, const ClipperLib_Z::Paths &clip, ClipperLib_Z::ClipType clipType)
-{
- ClipperLib_Z::Clipper clipper;
- clipper.ZFillFunction([](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, const ClipperLib_Z::IntPoint &e2bot,
- const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) {
- ClipperLib_Z::IntPoint start = e1bot;
- ClipperLib_Z::IntPoint end = e1top;
-
- if (start.z() <= 0 && end.z() <= 0) {
- start = e2bot;
- end = e2top;
- }
-
- assert(start.z() > 0 && end.z() > 0);
-
- // Interpolate extrusion line width.
- double length_sqr = (end - start).cast<double>().squaredNorm();
- double dist_sqr = (pt - start).cast<double>().squaredNorm();
- double t = std::sqrt(dist_sqr / length_sqr);
-
- pt.z() = start.z() + coord_t((end.z() - start.z()) * t);
- });
-
- clipper.AddPaths(subjects, ClipperLib_Z::ptSubject, false);
- clipper.AddPaths(clip, ClipperLib_Z::ptClip, true);
-
- ClipperLib_Z::PolyTree clipped_polytree;
- ClipperLib_Z::Paths clipped_paths;
- clipper.Execute(clipType, clipped_polytree, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero);
- ClipperLib_Z::PolyTreeToPaths(clipped_polytree, clipped_paths);
-
- // Clipped path could contain vertices from the clip with a Z coordinate equal to zero.
- // For those vertices, we must assign value based on the subject.
- // This happens only in sporadic cases.
- for (ClipperLib_Z::Path &path : clipped_paths)
- for (ClipperLib_Z::IntPoint &c_pt : path)
- if (c_pt.z() == 0) {
- const Point pt(c_pt.x(), c_pt.y());
- Point projected_pt_min;
- const ClipperLib_Z::IntPoint* it_a = nullptr;
- const ClipperLib_Z::IntPoint* it_b = nullptr;
- auto dist_sqr_min = std::numeric_limits<double>::max();
- Point prev(0,0);
- for (const ClipperLib_Z::Path& subject : subjects) {
- // Now we must find the corresponding line on with this point is located and compute line width (Z coordinate).
- if (subject.size() <= 2)
- continue;
-
- for (auto it = std::next(subject.begin()); it != subject.end(); ++it) {
- Point curr(it->x(), it->y());
- if (it_a == nullptr) {
- assert(std::prev(it) == subject.begin());
- prev = Point(subject.front().x(), subject.front().y());
- }
- Point projected_pt = pt.projection_onto(Line(prev, curr));
- if (double dist_sqr = (projected_pt - pt).cast<double>().squaredNorm(); dist_sqr < dist_sqr_min) {
- dist_sqr_min = dist_sqr;
- projected_pt_min = projected_pt;
- it_a = &*std::prev(it);
- it_b = &*it;
- }
- prev = curr;
- }
-
- assert(dist_sqr_min <= SCALED_EPSILON);
- assert(*it_a != subject.back());
- }
-
- const Point pt_a(it_a->x(), it_a->y());
- const Point pt_b(it_b->x(), it_b->y());
- const double line_len = (pt_b - pt_a).cast<double>().norm();
- const double dist = (projected_pt_min - pt_a).cast<double>().norm();
- c_pt.z() = coord_t(double(it_a->z()) + (dist / line_len) * double(it_b->z() - it_a->z()));
- }
- assert([&clipped_paths = std::as_const(clipped_paths)]() -> bool {
- for (const ClipperLib_Z::Path &path : clipped_paths)
- for (const ClipperLib_Z::IntPoint &pt : path)
- if (pt.z() <= 0)
- return false;
- return true;
- }());
-
- return clipped_paths;
-}
-
void convert_to_clipperpath(const Polygons& source, ClipperLib_Z::Paths& dest) {
dest.clear();
dest.reserve(source.size());
@@ -2049,8 +1963,9 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const Polyline& loop_polygon
}
-ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& loop_polygons, ExtrusionRole role, bool is_external) const {
+ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& arachne_path, ExtrusionRole role, bool is_external) const {
ExtrusionPaths paths;
+ const bool is_loop = Point{ arachne_path.front().x(), arachne_path.front().y() }.coincides_with_epsilon(Point{ arachne_path.back().x(), arachne_path.back().y() });
const double overhangs_width = this->config->overhangs_width.get_abs_value(this->overhang_flow.nozzle_diameter());
const double overhangs_width_speed = this->config->overhangs_width_speed.get_abs_value(this->overhang_flow.nozzle_diameter());
if (0 == overhangs_width && 0 == overhangs_width_speed) {
@@ -2058,7 +1973,7 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& lo
//assert(path.mm3_per_mm == path.mm3_per_mm);
//assert(path.width == path.width);
//assert(path.height == path.height);
- append(paths, Geometry::variable_width(Arachne::to_thick_polyline(loop_polygons),
+ append(paths, Geometry::variable_width(Arachne::to_thick_polyline(arachne_path),
role,
is_external ? this->ext_perimeter_flow : this->perimeter_flow,
std::max(this->ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)),
@@ -2068,7 +1983,7 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& lo
}
//set the fan & speed before the flow
- ClipperLib_Z::Paths ok_polylines = { loop_polygons };
+ ClipperLib_Z::Paths ok_polylines = { arachne_path };
ClipperLib_Z::Paths small_speed;
ClipperLib_Z::Paths big_speed;
@@ -2264,7 +2179,7 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& lo
bool has_speed = !small_speed.empty() || !big_speed.empty();
bool has_flow = !small_flow.empty() || !big_flow.empty();
- std::function<void(ExtrusionPaths&, const std::function<bool(ExtrusionPath&, ExtrusionPath&, ExtrusionPath&)>&)> foreach = [](ExtrusionPaths& paths, const std::function<bool(ExtrusionPath&, ExtrusionPath&, ExtrusionPath&)>& doforeach) {
+ std::function<void(ExtrusionPaths&, const std::function<bool(ExtrusionPath&, ExtrusionPath&, ExtrusionPath&)>&)> foreach = [is_loop](ExtrusionPaths& paths, const std::function<bool(ExtrusionPath&, ExtrusionPath&, ExtrusionPath&)>& doforeach) {
if (paths.size() > 2)
for (int i = 1; i < paths.size() - 1; i++) {
if (doforeach(paths[i - 1], paths[i], paths[i + 1])) {
@@ -2276,22 +2191,26 @@ ExtrusionPaths PerimeterGenerator::create_overhangs(const ClipperLib_Z::Path& lo
}
}
}
- if (paths.size() > 2)
- if (doforeach(paths[paths.size() - 2], paths.back(), paths.front())) {
- paths.erase(paths.end() - 1);
- if (paths.back().height == paths.front().height) {
- paths.front().polyline.points.insert(paths.front().polyline.points.begin(), paths.back().polyline.points.begin(), paths.back().polyline.points.end() - 1);
+ if (is_loop) {
+ if (paths.size() > 2) {
+ if (doforeach(paths[paths.size() - 2], paths.back(), paths.front())) {
paths.erase(paths.end() - 1);
+ if (paths.back().height == paths.front().height) {
+ paths.front().polyline.points.insert(paths.front().polyline.points.begin(), paths.back().polyline.points.begin(), paths.back().polyline.points.end() - 1);
+ paths.erase(paths.end() - 1);
+ }
}
}
- if (paths.size() > 2)
- if (doforeach(paths.back(), paths.front(), paths[1])) {
- paths.erase(paths.begin());
- if (paths.back().height == paths.front().height) {
- paths.front().polyline.points.insert(paths.front().polyline.points.begin(), paths.back().polyline.points.begin(), paths.back().polyline.points.end() - 1);
- paths.erase(paths.end() - 1);
+ if (paths.size() > 2) {
+ if (doforeach(paths.back(), paths.front(), paths[1])) {
+ paths.erase(paths.begin());
+ if (paths.back().height == paths.front().height) {
+ paths.front().polyline.points.insert(paths.front().polyline.points.begin(), paths.back().polyline.points.begin(), paths.back().polyline.points.end() - 1);
+ paths.erase(paths.end() - 1);
+ }
}
}
+ }
};
if (paths.size() > 2) {
@@ -2393,12 +2312,11 @@ static void fuzzy_paths(ExtrusionPaths& paths, coordf_t fuzzy_skin_thickness, co
//not always a loop, with arachne
bool is_loop = paths.front().first_point() == last_point;
#ifdef _DEBUG
- assert(paths.back().last_point() == paths.front().first_point());
+ if (is_loop)
+ assert(paths.back().last_point() == paths.front().first_point());
for (int i = 1; i < paths.size(); i++) {
assert(paths[i - 1].last_point() == paths[i].first_point());
}
- if (is_loop)
- assert(paths.front().polyline.points.front() == paths.back().polyline.points.back());
#endif
Point p0 = is_loop ? last_point : paths.front().first_point();
const Point* previous_point = is_loop ? &last_point : &paths.front().first_point();
@@ -2438,7 +2356,8 @@ static void fuzzy_paths(ExtrusionPaths& paths, coordf_t fuzzy_skin_thickness, co
paths.back().polyline.points.push_back(last_point);
}
#ifdef _DEBUG
- assert(paths.back().last_point() == paths.front().first_point());
+ if (is_loop)
+ assert(paths.back().last_point() == paths.front().first_point());
for (int i = 1; i < paths.size(); i++) {
assert(paths[i - 1].last_point() == paths[i].first_point());
}
@@ -2580,13 +2499,21 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
ExtrusionEntityCollection PerimeterGenerator::_traverse_extrusions(std::vector<PerimeterGeneratorArachneExtrusion>& pg_extrusions)
{
ExtrusionEntityCollection extrusion_coll;
+ size_t biggest_inset_idx = 0;
+ for (PerimeterGeneratorArachneExtrusion& pg_extrusion : pg_extrusions) {
+ biggest_inset_idx = std::max(biggest_inset_idx, pg_extrusion.extrusion->inset_idx);
+ }
for (PerimeterGeneratorArachneExtrusion& pg_extrusion : pg_extrusions) {
Arachne::ExtrusionLine* extrusion = pg_extrusion.extrusion;
- if (extrusion->empty())
+ if (extrusion->isZeroLength())
continue;
const bool is_external = extrusion->inset_idx == 0;
ExtrusionRole role = is_external ? erExternalPerimeter : erPerimeter;
+ ExtrusionLoopRole loop_role = ExtrusionLoopRole::elrDefault;
+ if (biggest_inset_idx == extrusion->inset_idx) {
+ loop_role = ExtrusionLoopRole(ExtrusionLoopRole::elrInternal | ExtrusionLoopRole::elrFirstLoop);
+ }
// fuzzy_extrusion_line() don't work. I can use fuzzy_paths() anyway, not a big deal.
//if (pg_extrusion.fuzzify)
@@ -2599,8 +2526,12 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_extrusions(std::vector<P
this->object_config->support_material_contact_distance.value == 0)) {
ClipperLib_Z::Path extrusion_path;
extrusion_path.reserve(extrusion->size());
- for (const Arachne::ExtrusionJunction& ej : extrusion->junctions)
- extrusion_path.emplace_back(ej.p.x(), ej.p.y(), ej.w);
+ for (const Arachne::ExtrusionJunction& ej : extrusion->junctions) {
+ //remove duplicate poitns from arachne
+ if(extrusion_path.empty() ||
+ (ej.p.x() != extrusion_path.back().x() || ej.p.y() != extrusion_path.back().y()))
+ extrusion_path.emplace_back(ej.p.x(), ej.p.y(), ej.w);
+ }
paths = this->create_overhangs(extrusion_path, role, is_external);
// Reapply the nearest point search for starting point.
@@ -2659,7 +2590,7 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_extrusions(std::vector<P
// Append paths to collection.
if (!paths.empty()) {
if (extrusion->is_closed) {
- ExtrusionLoop extrusion_loop(std::move(paths));
+ ExtrusionLoop extrusion_loop(std::move(paths), loop_role);
// Restore the orientation of the extrusion loop.
//TODO: use if (loop.is_steep_overhang && this->layer->id() % 2 == 1) to make_clockwise => need to detect is_steep_overhang on the arachne path
if (pg_extrusion.is_contour)
diff --git a/src/libslic3r/ShortestPath.cpp b/src/libslic3r/ShortestPath.cpp
index aae443395..d5a920759 100644
--- a/src/libslic3r/ShortestPath.cpp
+++ b/src/libslic3r/ShortestPath.cpp
@@ -1069,6 +1069,13 @@ void reorder_extrusion_paths(std::vector<ExtrusionPath> &extrusion_paths, const
if (idx.second)
out.back().reverse();
}
+ //FIXME: TODO: find the real cause inside chain_extrusion_paths
+ // for now on, jsut verify & patch that
+ if (out.size() > 1
+ && !out.front().last_point().coincides_with_epsilon(out[1].first_point())
+ && out.front().first_point().coincides_with_epsilon(out[1].first_point())) {
+ out.front().reverse();
+ }
extrusion_paths.swap(out);
}
diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index c9d227a85..a263dd8c4 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -25,7 +25,7 @@
#include <boost/property_tree/ptree.hpp>
static const float GROUND_Z = -0.02f;
-static const std::array<float, 4> DEFAULT_GRID_COLOR = { 0.9f, 0.9, 0.9, 0.6f };
+static const std::array<float, 4> DEFAULT_GRID_COLOR = { 0.9f, 0.9f, 0.9f, 0.6f };
static const std::array<float, 4> DEFAULT_MODEL_COLOR = { 0.235f, 0.235f, 0.235f, 1.0f };
static const std::array<float, 4> PICKING_MODEL_COLOR = { 0.0f, 0.0f, 0.0f, 1.0f };
diff --git a/src/slic3r/GUI/FreeCADDialog.cpp b/src/slic3r/GUI/FreeCADDialog.cpp
index 959756f6d..271e3ef2d 100644
--- a/src/slic3r/GUI/FreeCADDialog.cpp
+++ b/src/slic3r/GUI/FreeCADDialog.cpp
@@ -784,7 +784,7 @@ bool FreeCADDialog::init_start_python() {
delete exec_var;
exec_var = new ExecVar();
-#ifdef __WINDO2WS__
+#ifdef __WINDOWS__
// Get the freecad path (python path)
boost::filesystem::path pythonpath(gui_app->app_config->get("freecad_path"));
if (pythonpath.filename().string().find("python") == std::string::npos) {