Browse Source

Finished porting convex_hull() to XS and removed dependency on Math::ConvexHull::MonotoneChain

Alessandro Ranellucci 11 years ago
parent
commit
de9d5403e8
5 changed files with 21 additions and 7 deletions
  1. 5 6
      lib/Slic3r/Print.pm
  2. 1 0
      xs/MANIFEST
  3. 7 0
      xs/src/Geometry.cpp
  4. 7 1
      xs/src/Point.cpp
  5. 1 0
      xs/src/Point.hpp

+ 5 - 6
lib/Slic3r/Print.pm

@@ -176,7 +176,6 @@ sub validate {
                 {
                     my @points = map Slic3r::Point->new(@$_[X,Y]), map @{$_->vertices}, @{$self->objects->[$obj_idx]->meshes};
                     my $convex_hull = convex_hull(\@points);
-                    use XXX; YYY ($convex_hull->pp);
                     ($clearance) = @{offset([$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND)};
                 }
                 for my $copy (@{$self->objects->[$obj_idx]->copies}) {
@@ -590,7 +589,7 @@ sub make_skirt {
     return if @points < 3;  # at least three points required for a convex hull
     
     # find out convex hull
-    my $convex_hull = convex_hull([ map $_->arrayref, @points ]);
+    my $convex_hull = convex_hull(\@points);
     
     my @extruded_length = ();  # for each extruder
     
@@ -606,7 +605,7 @@ sub make_skirt {
     my $distance = scale $Slic3r::Config->skirt_distance;
     for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) {
         $distance += scale $spacing;
-        my $loop = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND)->[0];
+        my $loop = offset([$convex_hull], $distance, 0.0001, JT_ROUND)->[0];
         $self->skirt->append(Slic3r::ExtrusionLoop->new(
             polygon         => Slic3r::Polygon->new(@$loop),
             role            => EXTR_ROLE_SKIRT,
@@ -777,7 +776,7 @@ sub write_gcode {
         my @islands = ();
         foreach my $obj_idx (0 .. $#{$self->objects}) {
             my $convex_hull = convex_hull([
-                map @{$_->contour->pp}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers},
+                map @{$_->contour}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers},
             ]);
             # discard layers only containing thin walls (offset would fail on an empty polygon)
             if (@$convex_hull) {
@@ -797,13 +796,13 @@ sub write_gcode {
     
     # calculate wiping points if needed
     if ($self->config->ooze_prevention) {
-        my $outer_skirt = Slic3r::Polygon->new(@{convex_hull([ map $_->pp, map @$_, @{$self->skirt} ])});
+        my $outer_skirt = convex_hull([ map @$_, @{$self->skirt} ]);
         my @skirts = ();
         foreach my $extruder (@{$self->extruders}) {
             push @skirts, my $s = $outer_skirt->clone;
             $s->translate(map scale($_), @{$extruder->extruder_offset});
         }
-        my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @$_, map $_->pp, @skirts ])});
+        my $convex_hull = convex_hull([ map @$_, @skirts ]);
         $gcodegen->standby_points([ map $_->clone, map @$_, map $_->subdivide(scale 10), @{offset([$convex_hull], scale 3)} ]);
     }
     

+ 1 - 0
xs/MANIFEST

@@ -36,6 +36,7 @@ src/PolylineCollection.hpp
 src/ppport.h
 src/Surface.cpp
 src/Surface.hpp
+src/SurfaceCollection.cpp
 src/SurfaceCollection.hpp
 src/SVG.cpp
 src/SVG.hpp

+ 7 - 0
xs/src/Geometry.cpp

@@ -9,6 +9,9 @@ sort_points (Point a, Point b)
     return (a.x < b.x) || (a.x == b.x && a.y < b.y);
 }
 
+/* This implementation is based on Steffen Mueller's work for 
+   the Perl module Math::ConvexHull::MonotoneChain (available 
+   on CPAN under the GPL terms) */
 void
 convex_hull(Points points, Polygon &hull)
 {
@@ -40,6 +43,10 @@ convex_hull(Points points, Polygon &hull)
         hull.points.push_back(*(out_hull[i]));
     }
     
+    // not sure why this happens randomly
+    if (hull.points.front().coincides_with(hull.points.back()))
+        hull.points.pop_back();
+    
     free(out_hull);
 }
 

+ 7 - 1
xs/src/Point.cpp

@@ -30,7 +30,13 @@ Point::rotate(double angle, Point* center)
 bool
 Point::coincides_with(const Point* point) const
 {
-    return this->x == point->x && this->y == point->y;
+    return this->coincides_with(*point);
+}
+
+bool
+Point::coincides_with(const Point &point) const
+{
+    return this->x == point.x && this->y == point.y;
 }
 
 int

+ 1 - 0
xs/src/Point.hpp

@@ -20,6 +20,7 @@ class Point
     void scale(double factor);
     void translate(double x, double y);
     void rotate(double angle, Point* center);
+    bool coincides_with(const Point &point) const;
     bool coincides_with(const Point* point) const;
     int nearest_point_index(const Points points) const;
     Point* nearest_point(Points points) const;