Просмотр исходного кода

Enforce seam alignment and blend in spiral vase. #2023

Alessandro Ranellucci 10 лет назад
Родитель
Сommit
f2c5e799b1

+ 5 - 1
lib/Slic3r/GCode.pm

@@ -185,7 +185,11 @@ sub extrude_loop {
     }
     
     # split the loop at the starting point
-    $loop->split_at($last_pos->nearest_point(\@candidates));
+    if ($self->config->spiral_vase) {
+        $loop->split_at($last_pos);
+    } else {
+        $loop->split_at_vertex($last_pos->nearest_point(\@candidates));
+    }
     
     # 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

+ 7 - 4
lib/Slic3r/GCode/SpiralVase.pm

@@ -43,7 +43,7 @@ sub process_layer {
         }
     });
     
-    #use XXX; YYY [ $gcode, $layer_height, $z, $total_layer_length ];
+    #use XXX; XXX [ $gcode, $layer_height, $z, $total_layer_length ];
     # remove layer height from initial Z
     $z -= $layer_height;
     
@@ -57,16 +57,19 @@ sub process_layer {
             my $line = $info->{raw};
             $line =~ s/ Z[.0-9]+/ Z$z/;
             $new_gcode .= "$line\n";
-        } elsif ($cmd eq 'G1' && !exists $args->{Z} && $info->{dist_XY}) {
+        } elsif ($cmd eq 'G1' && !exists($args->{Z}) && $info->{dist_XY}) {
             # horizontal move
             my $line = $info->{raw};
             if ($info->{extruding}) {
                 $z += $info->{dist_XY} * $layer_height / $total_layer_length;
                 $line =~ s/^G1 /sprintf 'G1 Z%.3f ', $z/e;
                 $new_gcode .= "$line\n";
-            } else {
-                $new_gcode .= "$line\n";
             }
+            # skip travel moves: the move to first perimeter point will
+            # cause a visible seam when loops are not aligned in XY; by skipping
+            # it we blend the first loop move in the XY plane (although the smoothness
+            # of such blend depend on how long the first segment is; maybe we should
+            # enforce some minimum length?)
         } else {
             $new_gcode .= "$info->{raw}\n";
         }

+ 36 - 3
xs/src/ExtrusionEntity.cpp

@@ -221,7 +221,7 @@ ExtrusionLoop::length() const
 }
 
 void
-ExtrusionLoop::split_at(const Point &point)
+ExtrusionLoop::split_at_vertex(const Point &point)
 {
     for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
         int idx = path->polyline.find_point(point);
@@ -239,7 +239,7 @@ ExtrusionLoop::split_at(const Point &point)
                 {
                     ExtrusionPath p = *path;
                     p.polyline.points.erase(p.polyline.points.begin(), p.polyline.points.begin() + idx);
-                    if (!p.polyline.points.empty()) new_paths.push_back(p);
+                    if (p.polyline.is_valid()) new_paths.push_back(p);
                 }
             
                 // then we add all paths until the end of current path list
@@ -252,7 +252,7 @@ ExtrusionLoop::split_at(const Point &point)
                 {
                     ExtrusionPath p = *path;
                     p.polyline.points.erase(p.polyline.points.begin() + idx + 1, p.polyline.points.end());
-                    if (!p.polyline.points.empty()) new_paths.push_back(p);
+                    if (p.polyline.is_valid()) new_paths.push_back(p);
                 }
                 // we can now override the old path list with the new one and stop looping
                 this->paths = new_paths;
@@ -263,6 +263,39 @@ ExtrusionLoop::split_at(const Point &point)
     CONFESS("Point not found");
 }
 
+void
+ExtrusionLoop::split_at(const Point &point)
+{
+    if (this->paths.empty()) return;
+    
+    // find the closest path and closest point
+    size_t path_idx = 0;
+    Point p = this->paths.front().first_point();
+    double min = point.distance_to(p);
+    for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
+        Point p_tmp = point.projection_onto(path->polyline);
+        double dist = point.distance_to(p_tmp);
+        if (dist < min) {
+            p = p_tmp;
+            min = dist;
+            path_idx = path - this->paths.begin();
+        }
+    }
+    
+    // now split path_idx in two parts
+    ExtrusionPath p1 = this->paths[path_idx];
+    ExtrusionPath p2 = p1;
+    this->paths[path_idx].polyline.split_at(p, &p1.polyline, &p2.polyline);
+    
+    // install the two paths
+    this->paths.erase(this->paths.begin() + path_idx);
+    if (p2.polyline.is_valid()) this->paths.insert(this->paths.begin() + path_idx, p2);
+    if (p1.polyline.is_valid()) this->paths.insert(this->paths.begin() + path_idx, p1);
+    
+    // split at the new vertex
+    this->split_at_vertex(p);
+}
+
 void
 ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
 {

+ 1 - 0
xs/src/ExtrusionEntity.hpp

@@ -93,6 +93,7 @@ class ExtrusionLoop : public ExtrusionEntity
     Point last_point() const;
     void polygon(Polygon* polygon) const;
     double length() const;
+    void split_at_vertex(const Point &point);
     void split_at(const Point &point);
     void clip_end(double distance, ExtrusionPaths* paths) const;
     bool has_overhang_point(const Point &point) const;

+ 6 - 0
xs/src/Point.cpp

@@ -6,6 +6,12 @@
 
 namespace Slic3r {
 
+Point::Point(double x, double y)
+{
+    this->x = lrint(x);
+    this->y = lrint(y);
+}
+
 bool
 Point::operator==(const Point& rhs) const
 {

+ 1 - 0
xs/src/Point.hpp

@@ -24,6 +24,7 @@ class Point
     coord_t x;
     coord_t y;
     explicit Point(coord_t _x = 0, coord_t _y = 0): x(_x), y(_y) {};
+    Point(double x, double y);
     bool operator==(const Point& rhs) const;
     std::string wkt() const;
     void scale(double factor);

+ 1 - 1
xs/src/Polygon.cpp

@@ -56,7 +56,7 @@ Polygon::lines(Lines* lines) const
 }
 
 void
-Polygon::split_at(const Point &point, Polyline* polyline) const
+Polygon::split_at_vertex(const Point &point, Polyline* polyline) const
 {
     // find index of point
     for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) {

+ 1 - 1
xs/src/Polygon.hpp

@@ -21,7 +21,7 @@ class Polygon : public MultiPoint {
     Point last_point() const;
     Lines lines() const;
     void lines(Lines* lines) const;
-    void split_at(const Point &point, Polyline* polyline) const;
+    void split_at_vertex(const Point &point, Polyline* polyline) const;
     void split_at_index(int index, Polyline* polyline) const;
     void split_at_first_point(Polyline* polyline) const;
     void equally_spaced_points(double distance, Points* points) const;

+ 36 - 0
xs/src/Polyline.cpp

@@ -117,6 +117,42 @@ Polyline::simplify(double tolerance)
     this->points = MultiPoint::_douglas_peucker(this->points, tolerance);
 }
 
+void
+Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const
+{
+    if (this->points.empty()) return;
+    
+    // find the line to split at
+    size_t line_idx = 0;
+    Point p = this->first_point();
+    double min = point.distance_to(p);
+    Lines lines = this->lines();
+    for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) {
+        Point p_tmp = point.projection_onto(*line);
+        if (point.distance_to(p_tmp) < min) {
+	        p = p_tmp;
+	        min = point.distance_to(p);
+	        line_idx = line - lines.begin();
+        }
+    }
+    
+    // create first half
+    p1->points.clear();
+    for (Lines::const_iterator line = lines.begin(); line != lines.begin() + line_idx + 1; ++line) {
+        if (!line->a.coincides_with(p)) p1->points.push_back(line->a);
+    }
+    // we add point instead of p because they might differ because of numerical issues
+    // and caller might want to rely on point belonging to result polylines
+    p1->points.push_back(point);
+    
+    // create second half
+    p2->points.clear();
+    p2->points.push_back(point);
+    for (Lines::const_iterator line = lines.begin() + line_idx; line != lines.end(); ++line) {
+        if (!line->b.coincides_with(p)) p2->points.push_back(line->b);
+    }
+}
+
 
 #ifdef SLIC3RXS
 REGISTER_CLASS(Polyline, "Polyline");

+ 1 - 0
xs/src/Polyline.hpp

@@ -21,6 +21,7 @@ class Polyline : public MultiPoint {
     void extend_start(double distance);
     void equally_spaced_points(double distance, Points* points) const;
     void simplify(double tolerance);
+    void split_at(const Point &point, Polyline* p1, Polyline* p2) const;
     
     #ifdef SLIC3RXS
     void from_SV_check(SV* poly_sv);

Некоторые файлы не были показаны из-за большого количества измененных файлов