Browse Source

New module to output SVG vertical sections of extrusion paths with real width and height. The commit includes a bugfix to the Polyline->grow() method and some simplification in the Line class which is now child of Polyline

Alessandro Ranellucci 12 years ago
parent
commit
bc9ff47d3f
7 changed files with 138 additions and 45 deletions
  1. 1 0
      MANIFEST
  2. 0 5
      lib/Slic3r/ExPolygon.pm
  3. 3 24
      lib/Slic3r/Line.pm
  4. 0 10
      lib/Slic3r/Polygon.pm
  5. 5 6
      lib/Slic3r/Polyline.pm
  6. 4 0
      lib/Slic3r/Print.pm
  7. 125 0
      lib/Slic3r/Test/SectionCut.pm

+ 1 - 0
MANIFEST

@@ -51,6 +51,7 @@ lib/Slic3r/Print/Object.pm
 lib/Slic3r/Surface.pm
 lib/Slic3r/SVG.pm
 lib/Slic3r/Test.pm
+lib/Slic3r/Test/SectionCut.pm
 lib/Slic3r/TriangleMesh.pm
 MANIFEST			This list of files
 README.markdown

+ 0 - 5
lib/Slic3r/ExPolygon.pm

@@ -73,11 +73,6 @@ sub is_printable {
     return Slic3r::Geometry::Clipper::offset($self, -$width / 2) ? 1 : 0;
 }
 
-sub boost_polygon {
-    my $self = shift;
-    return Boost::Geometry::Utils::polygon(@$self);
-}
-
 sub wkt {
     my $self = shift;
     return sprintf "POLYGON(%s)", 

+ 3 - 24
lib/Slic3r/Line.pm

@@ -2,7 +2,9 @@ package Slic3r::Line;
 use strict;
 use warnings;
 
-use Boost::Geometry::Utils;
+# a line is a two-points line
+use parent 'Slic3r::Polyline';
+
 use Slic3r::Geometry qw(A B X Y);
 
 sub new {
@@ -14,11 +16,6 @@ sub new {
     return $self;
 }
 
-sub boost_linestring {
-    my $self = shift;
-    return Boost::Geometry::Utils::linestring($self);
-}
-
 sub coincides_with {
     my $self = shift;
     my ($line) = @_;
@@ -27,11 +24,6 @@ sub coincides_with {
         || ($self->a->coincides_with($line->b) && $self->b->coincides_with($line->a));
 }
 
-sub length {
-    my $self = shift;
-    return Boost::Geometry::Utils::linestring_length($self);
-}
-
 sub vector {
     my $self = shift;
     return (ref $self)->new([0,0], [map $self->[B][$_] - $self->[A][$_], X,Y]);
@@ -67,17 +59,4 @@ sub midpoint {
     );
 }
 
-sub reverse {
-    my $self = shift;
-    @$self = reverse @$self;
-}
-
-sub translate {
-    my $self = shift;
-    my ($x, $y) = @_;
-    @$self = Slic3r::Geometry::move_points([$x, $y], @$self);
-    bless $_, 'Slic3r::Point' for @$self;
-    return $self;
-}
-
 1;

+ 0 - 10
lib/Slic3r/Polygon.pm

@@ -27,16 +27,6 @@ sub lines {
     return polygon_lines($self);
 }
 
-sub boost_polygon {
-    my $self = shift;
-    return Boost::Geometry::Utils::polygon($self);
-}
-
-sub boost_linestring {
-    my $self = shift;
-    return Boost::Geometry::Utils::linestring([@$self, $self->[0]]);
-}
-
 sub wkt {
     my $self = shift;
     return sprintf "POLYGON((%s))", join ',', map "$_->[0] $_->[1]", @$self;

+ 5 - 6
lib/Slic3r/Polyline.pm

@@ -5,6 +5,7 @@ use warnings;
 use Scalar::Util qw(reftype);
 use Slic3r::Geometry qw(A B X Y X1 X2 Y1 Y2 polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
     polyline_lines move_points same_point);
+use Slic3r::Geometry::Clipper qw(JT_SQUARE);
 
 # the constructor accepts an array(ref) of points
 sub new {
@@ -44,11 +45,6 @@ sub lines {
     return polyline_lines($self);
 }
 
-sub boost_linestring {
-    my $self = shift;
-    return Boost::Geometry::Utils::linestring($self);
-}
-
 sub wkt {
     my $self = shift;
     return sprintf "LINESTRING((%s))", join ',', map "$_->[0] $_->[1]", @$self;
@@ -84,10 +80,13 @@ sub length {
 
 sub grow {
     my $self = shift;
+    my ($distance, $scale, $joinType, $miterLimit) = @_;
+    $joinType //= JT_SQUARE;
+    
     return map Slic3r::Polygon->new($_),
         Slic3r::Geometry::Clipper::offset(
             [ Slic3r::Polygon->new(@$self, CORE::reverse @$self[1..($#$self-1)]) ],
-            @_,
+            $distance, $scale, $joinType, $miterLimit,
         );
 }
 

+ 4 - 0
lib/Slic3r/Print.pm

@@ -466,6 +466,10 @@ sub export_gcode {
         printf "  fills         = %.1fMb\n", List::Util::sum(map Devel::Size::total_size($_->fills), map @{$_->regions}, map @{$_->layers}, @{$self->objects})/1024/1024;
         printf "  print object  = %.1fMb\n", Devel::Size::total_size($self)/1024/1024;
     }
+    if (0) {
+        eval "use Slic3r::Test::SectionCut";
+        Slic3r::Test::SectionCut->new(print => $self)->export_svg("section_cut.svg");
+    }
     
     # output everything to a G-code file
     my $output_file = $self->expanded_output_filepath($params{output_file});

+ 125 - 0
lib/Slic3r/Test/SectionCut.pm

@@ -0,0 +1,125 @@
+package Slic3r::Test::SectionCut;
+use Moo;
+
+use Slic3r::Geometry qw(X Y A B X1 Y1 X2 Y2 unscale);
+use Slic3r::Geometry::Clipper qw(union_ex);
+use SVG;
+
+has 'scale' => (is => 'ro', default => sub {30});
+has 'print' => (is => 'ro', required => 1);
+has 'y_percent' => (is => 'ro', required => 1, default => sub {0.5});
+has 'line'  => (is => 'lazy');
+has 'height' => (is => 'rw');
+
+sub _build_line {
+    my $self = shift;
+    
+    my @bb = $self->print->bounding_box;
+    my $y = ($bb[Y2]-$bb[Y1]) * $self->y_percent;
+    return [ [ $bb[X1], $y ], [ $bb[X2], $y ] ]
+}
+
+sub export_svg {
+    my $self = shift;
+    my ($filename) = @_;
+    
+    my $print_size = $self->print->size;
+    $self->height(unscale($print_size->[X]));
+    my $svg = SVG->new(
+        width  => $self->scale * unscale($print_size->[X]),
+        height => $self->scale * $self->height,
+    );
+    
+    my $group = sub {
+        my %p = @_;
+        my $g = $svg->group(style => $p{style});
+        $g->rectangle(%$_) for $self->_get_rectangles($p{filter});
+    };
+    
+    $group->(
+        filter => sub { map @{$_->perimeters}, @{$_[0]->regions} },
+        style  => {
+            'stroke-width'  => 1,
+            'stroke'        => 'grey',
+            'fill'          => 'red',
+        },
+    );
+    
+    $group->(
+        filter => sub { map @{$_->fills}, @{$_[0]->regions} },
+        style  => {
+            'stroke-width'  => 1,
+            'stroke'        => '#444444',
+            'fill'          => 'grey',
+        },
+    );
+    
+    $group->(
+        filter => sub { $_[0]->support_fills, $_[0]->support_contact_fills },
+        style  => {
+            'stroke-width'  => 1,
+            'stroke'        => '#444444',
+            'fill'          => '#22FF00',
+        },
+    );
+    
+    Slic3r::open(\my $fh, '>', $filename);
+    print $fh $svg->xmlify;
+    close $fh;
+    printf "Section cut SVG written to %s\n", $filename;
+}
+
+sub _get_rectangles {
+    my $self = shift;
+    my ($filter) = @_;
+    
+    my @rectangles = ();
+    
+    foreach my $object (@{$self->print->objects}) {
+        foreach my $copy (@{$object->copies}) {
+            foreach my $layer (@{$object->layers}) {
+                # get all ExtrusionPath objects
+                my @paths = 
+                    map { $_->polyline->translate(@$copy); $_ }
+                    map { $_->isa('Slic3r::ExtrusionLoop') ? $_->split_at_first_point : $_ }
+                    map { ref($_) =~ /::Packed$/ ? $_->unpack : $_ }
+                    map { $_->isa('Slic3r::ExtrusionPath::Collection') ? @{$_->paths} : $_ }
+                    grep defined $_,
+                    $filter->($layer);
+                
+                foreach my $path (@paths) {
+                    foreach my $line ($path->lines) {
+                        my @intersections = @{ Boost::Geometry::Utils::polygon_multi_linestring_intersection(
+                            Slic3r::ExPolygon->new($line->grow(Slic3r::Geometry::scale $path->flow_spacing/2)),
+                            [ $self->line ],
+                        ) };
+                        
+                        push @rectangles, map {
+                            die "Intersection has more than two points!\n" if @$_ > 2;
+                            my $height = $path->height // $layer->height;
+                            {
+                                'x'         => $self->scale * unscale $_->[A][X],
+                                'y'         => $self->scale * $self->_y(unscale($layer->print_z)),
+                                'width'     => $self->scale * unscale(abs($_->[B][X] - $_->[A][X])),
+                                'height'    => $self->scale * $height,
+                                'rx'        => $self->scale * $height * 0.35,
+                                'ry'        => $self->scale * $height * 0.35,
+                            };
+                        } @intersections;
+                    }
+                }
+            }
+        }
+    }
+    
+    return @rectangles;
+}
+
+sub _y {
+    my $self = shift;
+    my ($y) = @_;
+    
+    return $self->height - $y;
+}
+
+1;