Browse Source

Refactoring: moved slicing code to new TriangleMesh class, leaving in STL just what's needed to read that particular input format. Slic3r will now warn if model is not manifold. #16

Alessandro Ranellucci 13 years ago
parent
commit
d51a37a0ae

+ 2 - 3
MANIFEST

@@ -26,9 +26,6 @@ lib/Slic3r/GUI/OptionsGroup.pm
 lib/Slic3r/GUI/SkeinPanel.pm
 lib/Slic3r/Layer.pm
 lib/Slic3r/Line.pm
-lib/Slic3r/Line/FacetEdge.pm
-lib/Slic3r/Line/FacetEdge/Bottom.pm
-lib/Slic3r/Line/FacetEdge/Top.pm
 lib/Slic3r/Perimeter.pm
 lib/Slic3r/Point.pm
 lib/Slic3r/Polygon.pm
@@ -39,6 +36,8 @@ lib/Slic3r/Skein.pm
 lib/Slic3r/STL.pm
 lib/Slic3r/Surface.pm
 lib/Slic3r/SVG.pm
+lib/Slic3r/TriangleMesh.pm
+lib/Slic3r/TriangleMesh/IntersectionLine.pm
 MANIFEST			This list of files
 README.markdown
 slic3r.pl

+ 4 - 3
lib/Slic3r.pm

@@ -3,7 +3,7 @@ package Slic3r;
 use strict;
 use warnings;
 
-our $VERSION = "0.5.3";
+our $VERSION = "0.5.4beta";
 
 our $debug = 0;
 sub debugf {
@@ -21,7 +21,6 @@ use Slic3r::Fill;
 use Slic3r::Geometry;
 use Slic3r::Layer;
 use Slic3r::Line;
-use Slic3r::Line::FacetEdge;
 use Slic3r::Perimeter;
 use Slic3r::Point;
 use Slic3r::Polygon;
@@ -31,6 +30,8 @@ use Slic3r::Print;
 use Slic3r::Skein;
 use Slic3r::STL;
 use Slic3r::Surface;
+use Slic3r::TriangleMesh;
+use Slic3r::TriangleMesh::IntersectionLine;
 
 # printer options
 our $nozzle_diameter    = 0.5;
@@ -60,7 +61,7 @@ our $layer_height           = 0.4;
 our $first_layer_height_ratio = 1;
 our $infill_every_layers    = 1;
 our $extrusion_width_ratio  = 0;
-our $flow_speed_ratio       = 1.1;
+our $flow_speed_ratio       = 1;
 our $flow_width;
 
 # print options

+ 9 - 2
lib/Slic3r/GUI/SkeinPanel.pm

@@ -4,7 +4,7 @@ use warnings;
 use utf8;
 
 use File::Basename qw(basename);
-use Wx qw(:sizer :progressdialog wxOK wxICON_INFORMATION wxICON_ERROR wxID_OK wxFD_OPEN
+use Wx qw(:sizer :progressdialog wxOK wxICON_INFORMATION wxICON_WARNING wxICON_ERROR wxID_OK wxFD_OPEN
     wxFD_SAVE wxDEFAULT wxNORMAL);
 use Wx::Event qw(EVT_BUTTON);
 use base 'Wx::Panel';
@@ -155,7 +155,14 @@ sub do_slice {
                 }
             },
         );
-        $skein->go;
+        {
+            local $SIG{__WARN__} = sub {
+                my $message = shift;
+                Wx::MessageDialog->new($self, $message, 'Non-manifold object', 
+                    wxOK | wxICON_WARNING)->ShowModal;
+            };
+            $skein->go;
+        }
         $process_dialog->Destroy;
         undef $process_dialog;
         

+ 45 - 3
lib/Slic3r/Geometry.pm

@@ -13,11 +13,11 @@ our @EXPORT_OK = qw(
     polygon_has_vertex polyline_length can_connect_points deg2rad rad2deg
     rotate_points move_points remove_coinciding_points clip_segment_polygon
     sum_vectors multiply_vector subtract_vectors dot perp polygon_points_visibility
-    line_intersection bounding_box bounding_box_intersect 
+    line_intersection bounding_box bounding_box_intersect same_point
     longest_segment angle3points three_points_aligned
     polyline_remove_parallel_continuous_edges polyline_remove_acute_vertices
     polygon_remove_acute_vertices polygon_remove_parallel_continuous_edges
-    shortest_path collinear
+    shortest_path collinear scale unscale merge_collinear_lines
 );
 
 use Slic3r::Geometry::DouglasPeucker qw(Douglas_Peucker);
@@ -35,9 +35,12 @@ use constant X2 => 2;
 use constant Y2 => 3;
 our $parallel_degrees_limit = abs(deg2rad(3));
 
-our $epsilon = 1E-4;
+our $epsilon = 1E-6;
 sub epsilon () { $epsilon }
 
+sub scale   ($) { $_[0] / $Slic3r::resolution }
+sub unscale ($) { $_[0] * $Slic3r::resolution }
+
 sub slope {
     my ($line) = @_;
     return undef if abs($line->[B][X] - $line->[A][X]) < epsilon;  # line is vertical
@@ -85,6 +88,11 @@ sub points_coincide {
     return 0;
 }
 
+sub same_point {
+    my ($p1, $p2) = @_;
+    return $p1->[X] == $p2->[X] && $p1->[Y] == $p2->[Y];
+}
+
 sub distance_between_points {
     my ($p1, $p2) = @_;
     return sqrt((($p1->[X] - $p2->[X])**2) + ($p1->[Y] - $p2->[Y])**2);
@@ -438,6 +446,40 @@ sub collinear {
     return 1;
 }
 
+sub merge_collinear_lines {
+    my ($lines) = @_;
+    my $line_count = @$lines;
+    
+    for (my $i = 0; $i <= $#$lines-1; $i++) {
+        for (my $j = $i+1; $j <= $#$lines; $j++) {
+            # lines are collinear and overlapping?
+            next unless collinear($lines->[$i], $lines->[$j], 1);
+            
+            # lines have same orientation?
+            next unless ($lines->[$i][A][X] <=> $lines->[$i][B][X]) == ($lines->[$j][A][X] <=> $lines->[$j][B][X])
+                && ($lines->[$i][A][Y] <=> $lines->[$i][B][Y]) == ($lines->[$j][A][Y] <=> $lines->[$j][B][Y]);
+            
+            # resulting line
+            my @x = sort { $a <=> $b } ($lines->[$i][A][X], $lines->[$i][B][X], $lines->[$j][A][X], $lines->[$j][B][X]);
+            my @y = sort { $a <=> $b } ($lines->[$i][A][Y], $lines->[$i][B][Y], $lines->[$j][A][Y], $lines->[$j][B][Y]);
+            my $new_line = Slic3r::Line->new([$x[0], $y[0]], [$x[-1], $y[-1]]);
+            for (X, Y) {
+                ($new_line->[A][$_], $new_line->[B][$_]) = ($new_line->[B][$_], $new_line->[A][$_])
+                    if $lines->[$i][A][$_] > $lines->[$i][B][$_];
+            }
+            
+            # save new line and remove found one
+            $lines->[$i] = $new_line;
+            splice @$lines, $j, 1;
+            $j--;
+        }
+    }
+    
+    Slic3r::debugf "  merging %d lines resulted in %d lines\n", $line_count, scalar(@$lines);
+    
+    return $lines;
+}
+
 sub _line_intersection {
   my ( $x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3 );
 

+ 5 - 189
lib/Slic3r/Layer.pm

@@ -2,8 +2,7 @@ package Slic3r::Layer;
 use Moo;
 
 use Math::Clipper ':all';
-use Slic3r::Geometry qw(polygon_lines points_coincide angle3points polyline_lines nearest_point
-    line_length collinear X Y A B PI);
+use Slic3r::Geometry qw(collinear X Y A B PI);
 use Slic3r::Geometry::Clipper qw(union_ex diff_ex intersection_ex PFT_EVENODD);
 use XXX;
 
@@ -18,7 +17,7 @@ has 'id' => (
 # these need to be merged in continuos (closed) polylines
 has 'lines' => (
     is      => 'rw',
-    #isa     => 'ArrayRef[Slic3r::Line]',
+    #isa     => 'ArrayRef[Slic3r::TriangleMesh::IntersectionLine]',
     default => sub { [] },
 );
 
@@ -98,202 +97,19 @@ sub add_line {
     my $self = shift;
     my ($line) = @_;
     
-    return if $line->a->coincides_with($line->b);
-    
     push @{ $self->lines }, $line;
     return $line;
 }
 
-# merge overlapping lines
-sub cleanup_lines {
-    my $self = shift;
-    
-    my $lines = $self->lines;
-    my $line_count = @$lines;
-    
-    for (my $i = 0; $i <= $#$lines-1; $i++) {
-        for (my $j = $i+1; $j <= $#$lines; $j++) {
-            # lines are collinear and overlapping?
-            next unless collinear($lines->[$i], $lines->[$j], 1);
-            
-            # lines have same orientation?
-            next unless ($lines->[$i][A][X] <=> $lines->[$i][B][X]) == ($lines->[$j][A][X] <=> $lines->[$j][B][X])
-                && ($lines->[$i][A][Y] <=> $lines->[$i][B][Y]) == ($lines->[$j][A][Y] <=> $lines->[$j][B][Y]);
-            
-            # resulting line
-            my @x = sort { $a <=> $b } ($lines->[$i][A][X], $lines->[$i][B][X], $lines->[$j][A][X], $lines->[$j][B][X]);
-            my @y = sort { $a <=> $b } ($lines->[$i][A][Y], $lines->[$i][B][Y], $lines->[$j][A][Y], $lines->[$j][B][Y]);
-            my $new_line = Slic3r::Line->new([$x[0], $y[0]], [$x[-1], $y[-1]]);
-            for (X, Y) {
-                ($new_line->[A][$_], $new_line->[B][$_]) = ($new_line->[B][$_], $new_line->[A][$_])
-                    if $lines->[$i][A][$_] > $lines->[$i][B][$_];
-            }
-            
-            # save new line and remove found one
-            $lines->[$i] = $new_line;
-            splice @$lines, $j, 1;
-            $j--;
-        }
-    }
-    
-    Slic3r::debugf "  merging %d lines resulted in %d lines\n", $line_count, scalar(@$lines);
-}
-
 # build polylines from lines
 sub make_surfaces {
     my $self = shift;
-    
-    if (0) {
-        printf "Layer was sliced at z = %f\n", $self->slice_z * $Slic3r::resolution;
-        require "Slic3r/SVG.pm";
-        Slic3r::SVG::output(undef, "lines.svg",
-            lines       => [ grep !$_->isa('Slic3r::Line::FacetEdge'), @{$self->lines} ],
-            red_lines   => [ grep  $_->isa('Slic3r::Line::FacetEdge'), @{$self->lines} ],
-        );
-    }
-    
-    my (@polygons, %visited_lines, @discarded_lines, @discarded_polylines) = ();
-    
-    my $detect = sub {
-        my @lines = @{$self->lines};
-        (@polygons, %visited_lines, @discarded_lines, @discarded_polylines) = ();
-        my $get_point_id = sub { sprintf "%.0f,%.0f", @{$_[0]} };
-        
-        my (%pointmap, @pointmap_keys) = ();
-        foreach my $line (@lines) {
-            my $point_id = $get_point_id->($line->[A]);
-            if (!exists $pointmap{$point_id}) {
-                $pointmap{$point_id} = [];
-                push @pointmap_keys, $line->[A];
-            }
-            push @{ $pointmap{$point_id} }, $line;
-        }
-        
-        my $n = 0;
-        while (my $first_line = shift @lines) {
-            next if $visited_lines{ $first_line->id };
-            my @points = @$first_line;
-            
-            my @seen_lines = ($first_line);
-            my %seen_points = map { $get_point_id->($points[$_]) => $_ } 0..1;
-            
-            CYCLE: while (1) {
-                my $next_lines = $pointmap{ $get_point_id->($points[-1]) };
-                
-                # shouldn't we find the point, let's try with a slower algorithm
-                # as approximation may make the coordinates differ
-                if (!$next_lines) {
-                    my $nearest_point = nearest_point($points[-1], \@pointmap_keys);
-                    #printf "  we have a nearest point: %f,%f (%s)\n", @$nearest_point, $get_point_id->($nearest_point);
-                    
-                    if ($nearest_point) {
-                        local $Slic3r::Geometry::epsilon = 1000000;
-                        $next_lines = $pointmap{$get_point_id->($nearest_point)}
-                            if points_coincide($points[-1], $nearest_point);
-                    }
-                }
-                
-                if (0 && !$next_lines) {
-                    require "Slic3r/SVG.pm";
-                    Slic3r::SVG::output(undef, "no_lines.svg",
-                        lines       => [ grep !$_->isa('Slic3r::Line::FacetEdge'), @{$self->lines} ],
-                        red_lines   => [ grep  $_->isa('Slic3r::Line::FacetEdge'), @{$self->lines} ],
-                        points      => [ $points[-1] ],
-                        no_arrows => 1,
-                    );
-                }
-                
-                $next_lines
-                    or die sprintf("No lines start at point %s. This shouldn't happen. Please check the model for manifoldness.\n", $get_point_id->($points[-1]));
-                last CYCLE if !@$next_lines;
-                
-                my @ordered_next_lines = sort 
-                    { angle3points($points[-1], $points[-2], $next_lines->[$a][B]) <=> angle3points($points[-1], $points[-2], $next_lines->[$b][B]) } 
-                    0..$#$next_lines;
-                
-                #if (@$next_lines > 1) {
-                #    Slic3r::SVG::output(undef, "next_line.svg",
-                #        lines        => $next_lines,
-                #        red_lines    => [ polyline_lines([@points]) ],
-                #        green_lines  => [ $next_lines->[ $ordered_next_lines[0] ] ],
-                #    );
-                #}
-                
-                my ($next_line) = splice @$next_lines, $ordered_next_lines[0], 1;
-                push @seen_lines, $next_line;
-                
-                push @points, $next_line->[B];
-                
-                my $point_id = $get_point_id->($points[-1]);
-                if ($seen_points{$point_id}) {
-                    splice @points, 0, $seen_points{$point_id};
-                    last CYCLE;
-                }
-                
-                $seen_points{$point_id} = $#points;
-            }
-            
-            if (@points < 4 || !points_coincide($points[0], $points[-1])) {
-                # discarding polyline
-                push @discarded_lines, @seen_lines;
-                if (@points > 2) {
-                    push @discarded_polylines, [@points];
-                }
-                next;
-            }
-            
-            $visited_lines{ $_->id } = 1 for @seen_lines;
-            pop @points;
-            Slic3r::debugf "Discovered polygon of %d points\n", scalar(@points);
-            push @polygons, Slic3r::Polygon->new(@points);
-            $polygons[-1]->cleanup;
-        }
-    };
-    
-    $detect->();
-    
-    # Now, if we got a clean and manifold model then @polygons would contain everything
-    # we need to draw our layer. In real life, sadly, things are different and it is likely
-    # that the above algorithm wasn't able to detect every polygon. This may happen because
-    # of non-manifoldness or because of many close lines, often overlapping; both situations
-    # make a head-to-tail search difficult.
-    # On the other hand, we can safely assume that every polygon we detected is correct, as 
-    # the above algorithm is quite strict. We can take a brute force approach to connect any
-    # other line.
-    
-    # So, let's first check what lines were not detected as part of polygons.
-    if (@discarded_lines) {
-        Slic3r::debugf "  %d lines out of %d were discarded and %d polylines were not closed\n",
-            scalar(@discarded_lines), scalar(@{$self->lines}), scalar(@discarded_polylines);
-        print "  Warning: errors while parsing this layer (dirty or non-manifold model).\n";
-        print "  Retrying with slower algorithm.\n";
-        
-        if (0) {
-            require "Slic3r/SVG.pm";
-            Slic3r::SVG::output(undef, "layer" . $self->id . "_detected.svg",
-                white_polygons => \@polygons,
-            );
-            Slic3r::SVG::output(undef, "layer" . $self->id . "_discarded_lines.svg",
-                red_lines   => \@discarded_lines,
-            );
-            Slic3r::SVG::output(undef, "layer" . $self->id . "_discarded_polylines.svg",
-                polylines   => \@discarded_polylines,
-            );
-        }
-        
-        $self->cleanup_lines;
-        eval { $detect->(); };
-        warn $@ if $@;
-        
-        if (@discarded_lines) {
-            print "  Warning: even slow detection algorithm threw errors. Review the output before printing.\n";
-        }
-    }
+    my ($loops) = @_;
     
     {
-        my $expolygons = union_ex([ @polygons ], PFT_EVENODD);
+        my $expolygons = union_ex($loops, PFT_EVENODD);
         Slic3r::debugf "  %d surface(s) having %d holes detected from %d polylines\n",
-            scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@polygons);
+            scalar(@$expolygons), scalar(map $_->holes, @$expolygons), scalar(@$loops);
         
         push @{$self->surfaces},
             map Slic3r::Surface->cast_from_expolygon($_, surface_type => 'internal'),

+ 0 - 9
lib/Slic3r/Line/FacetEdge.pm

@@ -1,9 +0,0 @@
-package Slic3r::Line::FacetEdge;
-use Moo;
-
-extends 'Slic3r::Line';
-
-use Slic3r::Line::FacetEdge::Bottom;
-use Slic3r::Line::FacetEdge::Top;
-
-1;

+ 0 - 6
lib/Slic3r/Line/FacetEdge/Bottom.pm

@@ -1,6 +0,0 @@
-package Slic3r::Line::FacetEdge::Bottom;
-use Moo;
-
-extends 'Slic3r::Line::FacetEdge';
-
-1;

+ 0 - 6
lib/Slic3r/Line/FacetEdge/Top.pm

@@ -1,6 +0,0 @@
-package Slic3r::Line::FacetEdge::Top;
-use Moo;
-
-extends 'Slic3r::Line::FacetEdge';
-
-1;

+ 57 - 6
lib/Slic3r/Print.pm

@@ -2,11 +2,14 @@ package Slic3r::Print;
 use Moo;
 
 use Math::ConvexHull 1.0.4 qw(convex_hull);
-use Slic3r::Geometry qw(X Y PI);
+use Slic3r::Geometry qw(X Y Z PI scale);
 use Slic3r::Geometry::Clipper qw(explode_expolygons safety_offset diff_ex intersection_ex
     union_ex offset JT_ROUND JT_MITER);
 use XXX;
 
+use constant MIN => 0;
+use constant MAX => 1;
+
 has 'x_length' => (
     is          => 'ro',
     required    => 1,
@@ -26,11 +29,59 @@ has 'layers' => (
     default => sub { [] },
 );
 
-sub new_from_stl {
-    my $self = shift;
-    my ($stl_file) = @_;
+sub new_from_mesh {
+    my $class = shift;
+    my ($mesh) = @_;
+    
+    $mesh->rotate($Slic3r::rotate);
+    $mesh->scale($Slic3r::scale / $Slic3r::resolution);
+    
+    # calculate the displacements needed to 
+    # have lowest value for each axis at coordinate 0
+    {
+        my @extents = $mesh->bounding_box;
+        my @shift = map -$extents[$_][MIN], X,Y,Z;
+        $mesh->move(@shift);
+    }
+    
+    # duplicate object
+    {
+        my @size = $mesh->size;
+        my @duplicate_offset = (
+            ($size[X] + scale $Slic3r::duplicate_distance),
+            ($size[Y] + scale $Slic3r::duplicate_distance),
+        );
+        for (my $i = 2; $i <= $Slic3r::duplicate_x; $i++) {
+            $mesh->duplicate($duplicate_offset[X] * ($i-1), 0);
+        }
+        for (my $i = 2; $i <= $Slic3r::duplicate_y; $i++) {
+            $mesh->duplicate(0, $duplicate_offset[Y] * ($i-1));
+        }
+    }
+    
+    # initialize print job
+    my @size = $mesh->size;
+    my $print = $class->new(
+        x_length => $size[X],
+        y_length => $size[Y],
+    );
+    
+    $mesh->make_edge_table;
+        
+    # process facets
+    for (my $i = 0; $i <= $#{$mesh->facets}; $i++) {
+        my $facet = $mesh->facets->[$i];
+        
+        # transform vertex coordinates
+        my ($normal, @vertices) = @$facet;
+        $mesh->_facet($print, $i, $normal, @vertices);
+    }
+    
+    die "Invalid input file\n" if !@{$print->layers};
     
-    my $print = Slic3r::STL->new->parse_file($stl_file);
+    # remove last layer if empty
+    # (we might have created it because of the $max_layer = ... + 1 code below)
+    pop @{$print->layers} if !@{$print->layers->[-1]->surfaces} && !@{$print->layers->[-1]->lines};
     
     print "\n==> PROCESSING SLICES:\n";
     foreach my $layer (@{ $print->layers }) {
@@ -44,7 +95,7 @@ sub new_from_stl {
         # inside a closed polyline)
         
         # build surfaces from sparse lines
-        $layer->make_surfaces;
+        $layer->make_surfaces($mesh->make_loops($layer));
     }
     
     return $print;

+ 1 - 200
lib/Slic3r/STL.pm

@@ -5,205 +5,6 @@ use Math::Clipper qw(integerize_coordinate_sets is_counter_clockwise);
 use Slic3r::Geometry qw(X Y Z three_points_aligned longest_segment);
 use XXX;
 
-use constant MIN => 0;
-use constant MAX => 1;
-
-sub parse_file {
-    my $self = shift;
-    my ($file) = @_;
-    
-    # open STL file
-    my $facets = $self->read_file($file);
-    
-    if ($Slic3r::rotate > 0) {
-        my $deg = Slic3r::Geometry::deg2rad($Slic3r::rotate);
-        foreach my $facet (@$facets) {
-            my ($normal, @vertices) = @$facet;
-            foreach my $vertex (@vertices) {
-                @$vertex = (@{ +(Slic3r::Geometry::rotate_points($deg, undef, [ $vertex->[X], $vertex->[Y] ]))[0] }, $vertex->[Z]);
-            }
-        }
-    }
-    
-    # we only want to work with positive coordinates, so let's 
-    # find our object extents to calculate coordinate displacements
-    my @extents = (map [99999999999, -99999999999], X,Y,Z);
-    foreach my $facet (@$facets) {
-        my ($normal, @vertices) = @$facet;
-        foreach my $vertex (@vertices) {
-            for (X,Y,Z) {
-                $extents[$_][MIN] = $vertex->[$_] if $vertex->[$_] < $extents[$_][MIN];
-                $extents[$_][MAX] = $vertex->[$_] if $vertex->[$_] > $extents[$_][MAX];
-            }
-        }
-    }
-    
-    # scale extents
-    for (X,Y,Z) {
-        $extents[$_][MIN] *= $Slic3r::scale;
-        $extents[$_][MAX] *= $Slic3r::scale;
-    }
-    
-    # duplicate object
-    my @duplicate_offset = (
-        (($extents[X][MAX] - $extents[X][MIN]) + $Slic3r::duplicate_distance),
-        (($extents[Y][MAX] - $extents[Y][MIN]) + $Slic3r::duplicate_distance),
-    );
-    $extents[X][MAX] += $duplicate_offset[X] * ($Slic3r::duplicate_x-1);
-    $extents[Y][MAX] += $duplicate_offset[Y] * ($Slic3r::duplicate_y-1);
-    my @copies = ();
-    for (my $i = 0; $i < $Slic3r::duplicate_x; $i++) {
-        for (my $j = 0; $j < $Slic3r::duplicate_y; $j++) {
-            push @copies, [ $duplicate_offset[X] * $i, $duplicate_offset[Y] * $j ];
-        }
-    }
-    
-    # initialize print job
-    my $print = Slic3r::Print->new(
-        x_length => ($extents[X][MAX] - $extents[X][MIN]) / $Slic3r::resolution,
-        y_length => ($extents[Y][MAX] - $extents[Y][MIN]) / $Slic3r::resolution,
-    );
-    
-    # calculate the displacements needed to 
-    # have lowest value for each axis at coordinate 0
-    my @shift = map sprintf('%.0f', -$extents[$_][MIN] / $Slic3r::resolution), X,Y,Z;
-    
-    # process facets
-    foreach my $facet (@$facets) {
-        
-        # transform vertex coordinates
-        my ($normal, @vertices) = @$facet;
-        foreach my $vertex (@vertices) {
-            $vertex->[$_] = ($Slic3r::scale * $vertex->[$_] / $Slic3r::resolution) + $shift[$_]
-                for X,Y,Z;
-        }
-        
-        foreach my $copy (@copies) {
-            my @copy_vertices = map [ @$_ ], @vertices;  # clone vertices
-            foreach my $vertex (@copy_vertices) {
-                $vertex->[$_] += $copy->[$_] / $Slic3r::resolution for X,Y;
-            }
-            $self->_facet($print, $normal, @copy_vertices);
-        }
-    }
-    
-    die "Invalid input file\n" if !@{$print->layers};
-    
-    # remove last layer if empty
-    # (we might have created it because of the $max_layer = ... + 1 code below)
-    pop @{$print->layers} if !@{$print->layers->[-1]->surfaces} && !@{$print->layers->[-1]->lines};
-    
-    return $print;
-}
-
-sub _facet {
-    my $self = shift;
-    my ($print, $normal, @vertices) = @_;
-    Slic3r::debugf "\n==> FACET (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", map @$_, @vertices
-        if $Slic3r::debug;
-    
-    # find the vertical extents of the facet
-    my ($min_z, $max_z) = (99999999999, -99999999999);
-    foreach my $vertex (@vertices) {
-        $min_z = $vertex->[Z] if $vertex->[Z] < $min_z;
-        $max_z = $vertex->[Z] if $vertex->[Z] > $max_z;
-    }
-    Slic3r::debugf "z: min = %.0f, max = %.0f\n", $min_z, $max_z;
-    
-    if ($min_z == $max_z) {
-        Slic3r::debugf "Facet is horizontal; ignoring\n";
-        return;
-    }
-    
-    # calculate the layer extents
-    # (the -1 and +1 here are used as a quick and dirty replacement for some
-    # complex calculation of the first layer height ratio logic)
-    my $min_layer = int($min_z * $Slic3r::resolution / $Slic3r::layer_height) - 1;
-    $min_layer = 0 if $min_layer < 0;
-    my $max_layer = int($max_z * $Slic3r::resolution / $Slic3r::layer_height) + 1;
-    Slic3r::debugf "layers: min = %s, max = %s\n", $min_layer, $max_layer;
-    
-    # reorder vertices so that the first one is the one with lowest Z
-    # this is needed to get all intersection lines in a consistent order
-    # (external on the right of the line)
-    {
-        my @z_order = sort { $vertices[$a][Z] <=> $vertices[$b][Z] } 0..2;
-        @vertices = (splice(@vertices, $z_order[0]), splice(@vertices, 0, $z_order[0]));
-    }
-    
-    for (my $layer_id = $min_layer; $layer_id <= $max_layer; $layer_id++) {
-        my $layer = $print->layer($layer_id);
-        $layer->add_line($_) for $self->intersect_facet(\@vertices, $layer->slice_z);
-    }
-}
-
-sub intersect_facet {
-    my $self = shift;
-    my ($vertices, $z) = @_;
-    
-    # build the three segments of the triangle facet
-    my @edges = (
-        [ $vertices->[0], $vertices->[1] ],
-        [ $vertices->[1], $vertices->[2] ],
-        [ $vertices->[2], $vertices->[0] ],
-    );
-    
-    my (@lines, @intersection_points) = ();
-        
-    foreach my $edge (@edges) {
-        my ($a, $b) = @$edge;
-        #printf "Az = %d, Bz = %d, z = %d\n", $a->[Z], $b->[Z], $z;
-        
-        if ($a->[Z] == $b->[Z] && $a->[Z] == $z) {
-            # edge is horizontal and belongs to the current layer
-            my $edge_type = (grep $_->[Z] > $z, @$vertices) ? 'Bottom' : 'Top';
-            ($a, $b) = ($b, $a) if $edge_type eq 'Bottom';
-            push @lines, "Slic3r::Line::FacetEdge::$edge_type"->new(
-                [$a->[X], $a->[Y]], [$b->[X], $b->[Y]],
-            );
-            #print "Horizontal edge at $z!\n";
-            
-        } elsif (($a->[Z] < $z && $b->[Z] > $z) || ($b->[Z] < $z && $a->[Z] > $z)) {
-            # edge intersects the current layer; calculate intersection
-            push @intersection_points, [
-                $b->[X] + ($a->[X] - $b->[X]) * ($z - $b->[Z]) / ($a->[Z] - $b->[Z]),
-                $b->[Y] + ($a->[Y] - $b->[Y]) * ($z - $b->[Z]) / ($a->[Z] - $b->[Z]),
-            ];
-            #print "Intersects at $z!\n";
-            
-        } elsif ($a->[Z] == $z) {
-            #print "A point on plane $z!\n";
-            push @intersection_points, [ $a->[X], $a->[Y] ];
-            
-        } elsif ($b->[Z] == $z) {
-            #print "B point on plane $z!\n";
-            push @intersection_points, [ $b->[X], $b->[Y] ];
-        }
-    }
-    
-    Slic3r::Geometry::remove_coinciding_points(\@intersection_points);
-    
-    if (@intersection_points > 1 && !@lines) {
-        
-        # remove coinciding points
-        
-        # defensive programming:
-        die "Facets must intersect each plane 0 or 2 times" if @intersection_points != 2;
-        
-        # check whether the two points coincide due to resolution rounding
-        #if ($intersection_points[0]->coincides_with($intersection_points[1])) {
-        #    Slic3r::debugf "Points coincide; removing\n";
-        #    return;
-        #}
-        
-        # connect points:
-        push @lines, Slic3r::Line->new(@intersection_points);
-        #printf "  intersection points = %f,%f - %f,%f\n", map @$_, @intersection_points;
-    }
-    
-    return @lines;
-}
-
 sub read_file {
     my $self = shift;
     my ($file) = @_;
@@ -238,7 +39,7 @@ sub read_file {
         : _read_binary($fh, $facets);
     
     close $fh;
-    return $facets;
+    return Slic3r::TriangleMesh->new(facets => $facets);
 }
 
 sub _read_ascii {

Some files were not shown because too many files changed in this diff