Merge branch 'master' into xs

This commit is contained in:
Alessandro Ranellucci 2013-06-23 12:27:12 +02:00
commit ff795f2918
13 changed files with 175 additions and 60 deletions

View File

@ -27,17 +27,29 @@ my %recommends = qw(
Class::XSAccessor 0 Class::XSAccessor 0
Growl::GNTP 0.15 Growl::GNTP 0.15
XML::SAX::ExpatXS 0 XML::SAX::ExpatXS 0
Wx 0.9901 );
# removed:
# Wx 0.9901
my @try = (
$ENV{CPANM} // (),
File::Spec->catfile($Config{sitebin}, 'cpanm'),
File::Spec->catfile($Config{installscript}, 'cpanm'),
); );
my $cpanm; my $cpanm;
if (defined $ENV{CPANM} && -x $ENV{CPANM}) { foreach my $path (@try) {
$cpanm = $ENV{CPANM}; if (-e $path) { # don't use -x because it fails on Windows
} elsif (-x (my $c = File::Spec->catfile($Config{installscript}, 'cpanm'))) { $cpanm = $path;
$cpanm = $c; last;
} elsif ($^O = /^(?:darwin|linux)$/ && system(qw(which cpanm)) == 0) { }
}
if (!$cpanm) {
if ($^O =~ /^(?:darwin|linux)$/ && system(qw(which cpanm)) == 0) {
$cpanm = 'cpanm'; $cpanm = 'cpanm';
} }
}
die <<'EOF' die <<'EOF'
cpanm was not found. Please install it before running this script. cpanm was not found. Please install it before running this script.

View File

@ -3,8 +3,8 @@ use Moo;
extends 'Slic3r::Fill::Base'; extends 'Slic3r::Fill::Base';
use Slic3r::Geometry qw(scale unscale X); use Slic3r::Geometry qw(scale unscale X nearest_point_index);
use Slic3r::Geometry::Clipper qw(offset2 union_pt traverse_pt PFT_EVENODD); use Slic3r::Geometry::Clipper qw(offset offset2 union_pt traverse_pt PFT_EVENODD);
sub fill_surface { sub fill_surface {
my $self = shift; my $self = shift;
@ -27,16 +27,26 @@ sub fill_surface {
$flow_spacing = unscale $distance; $flow_spacing = unscale $distance;
} }
my @loops = my @last = @$expolygon; # compensate the overlap which is good for rectilinear but harmful for concentric
# where the perimeter/infill spacing should be equal to any other loop spacing
my @loops = my @last = offset($expolygon, -&Slic3r::INFILL_OVERLAP_OVER_SPACING * $min_spacing / 2);
while (@last) { while (@last) {
push @loops, @last = offset2(\@last, -1.5*$distance, +0.5*$distance); push @loops, @last = offset2(\@last, -1.5*$distance, +0.5*$distance);
} }
# generate paths from the outermost to the innermost, to avoid # generate paths from the outermost to the innermost, to avoid
# adhesion problems of the first central tiny loops # adhesion problems of the first central tiny loops
my @paths = map Slic3r::Polygon->new(@$_)->split_at_first_point, @loops = map Slic3r::Polygon->new(@$_),
reverse traverse_pt( union_pt(\@loops, PFT_EVENODD) ); reverse traverse_pt( union_pt(\@loops, PFT_EVENODD) );
# order paths using a nearest neighbor search
my @paths = ();
my $last_pos = [0,0];
foreach my $loop (@loops) {
push @paths, $loop->split_at_index(nearest_point_index($last_pos, $loop));
$last_pos = $paths[-1][-1];
}
# clip the paths to avoid the extruder to get exactly on the first point of the loop # clip the paths to avoid the extruder to get exactly on the first point of the loop
my $clip_length = scale $flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING; my $clip_length = scale $flow_spacing * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_SPACING;
$_->clip_end($clip_length) for @paths; $_->clip_end($clip_length) for @paths;

View File

@ -190,8 +190,6 @@ sub extrude_loop {
$extrusion_path->intersect_expolygons($self->_layer_overhangs); $extrusion_path->intersect_expolygons($self->_layer_overhangs);
# reapply the nearest point search for starting point # reapply the nearest point search for starting point
# (TODO: choose the nearest point not on an overhang - make sure wipe and
# inwards move consider the new actual starting point)
@paths = Slic3r::ExtrusionPath::Collection @paths = Slic3r::ExtrusionPath::Collection
->new(paths => [@paths]) ->new(paths => [@paths])
->chained_path($last_pos, 1); ->chained_path($last_pos, 1);
@ -443,9 +441,16 @@ sub retract {
$self->speed('travel'); $self->speed('travel');
# subdivide the retraction # subdivide the retraction
my $retracted = 0;
for (1 .. $#$wipe_path) { for (1 .. $#$wipe_path) {
my $segment_length = $wipe_path->[$_-1]->distance_to($wipe_path->[$_]); my $segment_length = $wipe_path->[$_-1]->distance_to($wipe_path->[$_]);
$gcode .= $self->G1($wipe_path->[$_], undef, $retract->[2] * ($segment_length / $total_wipe_length), $retract->[3] . ";_WIPE"); $retracted += my $e = $retract->[2] * ($segment_length / $total_wipe_length);
$gcode .= $self->G1($wipe_path->[$_], undef, $e, $retract->[3] . ";_WIPE");
}
if ($retracted > $retract->[2]) {
# if we retracted less than we had to, retract the remainder
# TODO: add regression test
$gcode .= $self->G1(undef, undef, $retract->[2] - $retracted, $comment);
} }
} else { } else {
$self->speed('retract'); $self->speed('retract');

View File

@ -12,7 +12,7 @@ our @EXPORT_OK = qw(
point_is_on_left_of_segment polyline_lines polygon_lines nearest_point point_is_on_left_of_segment polyline_lines polygon_lines nearest_point
point_along_segment polygon_segment_having_point polygon_has_subsegment point_along_segment polygon_segment_having_point polygon_has_subsegment
polygon_has_vertex polyline_length can_connect_points deg2rad rad2deg polygon_has_vertex polyline_length can_connect_points deg2rad rad2deg
rotate_points move_points clip_segment_polygon rotate_points move_points clip_segment_polygon nearest_point_index
sum_vectors multiply_vector subtract_vectors dot perp polygon_points_visibility sum_vectors multiply_vector subtract_vectors dot perp polygon_points_visibility
line_intersection bounding_box bounding_box_intersect same_point same_line line_intersection bounding_box bounding_box_intersect same_point same_line
longest_segment angle3points three_points_aligned line_direction longest_segment angle3points three_points_aligned line_direction

View File

@ -62,6 +62,18 @@ sub scale {
$self; $self;
} }
sub translate {
my $self = shift;
my @shift = @_;
for my $axis (X .. $#{$self->extents}) {
$self->extents->[$axis][MIN] += $shift[$axis];
$self->extents->[$axis][MAX] += $shift[$axis];
}
$self;
}
sub size { sub size {
my $self = shift; my $self = shift;

View File

@ -256,7 +256,11 @@ sub make_perimeters {
foreach my $polynode (@nodes) { foreach my $polynode (@nodes) {
push @loops, $traverse->($polynode->{children}, $depth+1, $is_contour); push @loops, $traverse->($polynode->{children}, $depth+1, $is_contour);
# return ccw contours and cw holes
# GCode.pm will convert all of them to ccw, but it needs to know
# what the holes are in order to compute the correct inwards move
my $polygon = Slic3r::Polygon->new($polynode->{outer} // [ reverse @{$polynode->{hole}} ]); my $polygon = Slic3r::Polygon->new($polynode->{outer} // [ reverse @{$polynode->{hole}} ]);
$polygon->reverse if !$is_contour;
my $role = EXTR_ROLE_PERIMETER; my $role = EXTR_ROLE_PERIMETER;
if ($is_contour ? $depth == 0 : !@{ $polynode->{children} }) { if ($is_contour ? $depth == 0 : !@{ $polynode->{children} }) {

View File

@ -6,6 +6,7 @@ use Slic3r::Geometry qw(X Y Z MIN move_points);
has 'materials' => (is => 'ro', default => sub { {} }); has 'materials' => (is => 'ro', default => sub { {} });
has 'objects' => (is => 'ro', default => sub { [] }); has 'objects' => (is => 'ro', default => sub { [] });
has '_bounding_box' => (is => 'rw');
sub read_from_file { sub read_from_file {
my $class = shift; my $class = shift;
@ -57,6 +58,7 @@ sub add_object {
my $object = Slic3r::Model::Object->new(model => $self, @_); my $object = Slic3r::Model::Object->new(model => $self, @_);
push @{$self->objects}, $object; push @{$self->objects}, $object;
$self->_bounding_box(undef);
return $object; return $object;
} }
@ -70,11 +72,6 @@ sub set_material {
); );
} }
sub scale {
my $self = shift;
$_->scale(@_) for @{$self->objects};
}
sub arrange_objects { sub arrange_objects {
my $self = shift; my $self = shift;
my ($config) = @_; my ($config) = @_;
@ -151,8 +148,9 @@ sub _arrange {
return ($config->duplicate_grid->[X] * $config->duplicate_grid->[Y]), @positions; return ($config->duplicate_grid->[X] * $config->duplicate_grid->[Y]), @positions;
} else { } else {
my $total_parts = $config->duplicate * @items; my $total_parts = $config->duplicate * @items;
my $partx = max(map $_->size->[X], @items); my @sizes = map $_->size, @items;
my $party = max(map $_->size->[Y], @items); my $partx = max(map $_->[X], @sizes);
my $party = max(map $_->[Y], @sizes);
return $config->duplicate, return $config->duplicate,
Slic3r::Geometry::arrange Slic3r::Geometry::arrange
($total_parts, $partx, $party, (map $_, @{$config->bed_size}), ($total_parts, $partx, $party, (map $_, @{$config->bed_size}),
@ -172,12 +170,16 @@ sub used_vertices {
sub size { sub size {
my $self = shift; my $self = shift;
return [ Slic3r::Geometry::size_3D($self->used_vertices) ]; return $self->bounding_box->size;
} }
sub bounding_box { sub bounding_box {
my $self = shift; my $self = shift;
return Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices);
if (!defined $self->_bounding_box) {
$self->_bounding_box(Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices));
}
return $self->_bounding_box;
} }
sub align_to_origin { sub align_to_origin {
@ -198,9 +200,18 @@ sub align_to_origin {
} }
} }
sub scale {
my $self = shift;
$_->scale(@_) for @{$self->objects};
$self->_bounding_box->scale(@_) if defined $self->_bounding_box;
}
sub move { sub move {
my $self = shift; my $self = shift;
$_->move(@_) for @{$self->objects}; my @shift = @_;
$_->move(@shift) for @{$self->objects};
$self->_bounding_box->translate(@shift) if defined $self->_bounding_box;
} }
# flattens everything to a single mesh # flattens everything to a single mesh
@ -286,6 +297,7 @@ has 'vertices' => (is => 'ro', default => sub { [] });
has 'volumes' => (is => 'ro', default => sub { [] }); has 'volumes' => (is => 'ro', default => sub { [] });
has 'instances' => (is => 'rw'); has 'instances' => (is => 'rw');
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ] has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
has '_bounding_box' => (is => 'rw');
sub add_volume { sub add_volume {
my $self = shift; my $self = shift;
@ -304,6 +316,8 @@ sub add_volume {
my $volume = Slic3r::Model::Volume->new(object => $self, %args); my $volume = Slic3r::Model::Volume->new(object => $self, %args);
push @{$self->volumes}, $volume; push @{$self->volumes}, $volume;
$self->_bounding_box(undef);
$self->model->_bounding_box(undef);
return $volume; return $volume;
} }
@ -312,6 +326,7 @@ sub add_instance {
$self->instances([]) if !defined $self->instances; $self->instances([]) if !defined $self->instances;
push @{$self->instances}, Slic3r::Model::Instance->new(object => $self, @_); push @{$self->instances}, Slic3r::Model::Instance->new(object => $self, @_);
$self->model->_bounding_box(undef);
return $self->instances->[-1]; return $self->instances->[-1];
} }
@ -333,7 +348,7 @@ sub used_vertices {
sub size { sub size {
my $self = shift; my $self = shift;
return [ Slic3r::Geometry::size_3D($self->used_vertices) ]; return $self->bounding_box->size;
} }
sub center { sub center {
@ -343,7 +358,11 @@ sub center {
sub bounding_box { sub bounding_box {
my $self = shift; my $self = shift;
return Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices);
if (!defined $self->_bounding_box) {
$self->_bounding_box(Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices));
}
return $self->_bounding_box;
} }
sub align_to_origin { sub align_to_origin {
@ -359,7 +378,10 @@ sub align_to_origin {
sub move { sub move {
my $self = shift; my $self = shift;
@{$self->vertices} = move_points_3D([ @_ ], @{$self->vertices}); my @shift = @_;
@{$self->vertices} = move_points_3D([ @shift ], @{$self->vertices});
$self->_bounding_box->translate(@shift) if defined $self->_bounding_box;
} }
sub scale { sub scale {
@ -371,6 +393,8 @@ sub scale {
foreach my $vertex (@{$self->vertices}) { foreach my $vertex (@{$self->vertices}) {
$vertex->[$_] *= $factor for X,Y,Z; $vertex->[$_] *= $factor for X,Y,Z;
} }
$self->_bounding_box->scale($factor) if defined $self->_bounding_box;
} }
sub rotate { sub rotate {
@ -384,6 +408,8 @@ sub rotate {
foreach my $vertex (@{$self->vertices}) { foreach my $vertex (@{$self->vertices}) {
@$vertex = (@{ +(Slic3r::Geometry::rotate_points($rad, undef, [ $vertex->[X], $vertex->[Y] ]))[0] }, $vertex->[Z]); @$vertex = (@{ +(Slic3r::Geometry::rotate_points($rad, undef, [ $vertex->[X], $vertex->[Y] ]))[0] }, $vertex->[Z]);
} }
$self->_bounding_box(undef);
} }
sub materials_count { sub materials_count {

View File

@ -7,7 +7,7 @@ use parent 'Slic3r::Polyline';
use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges use Slic3r::Geometry qw(polygon_lines polygon_remove_parallel_continuous_edges
polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon polygon_remove_acute_vertices polygon_segment_having_point point_in_polygon
PI X1 X2 Y1 Y2); PI X1 X2 Y1 Y2 epsilon);
use Slic3r::Geometry::Clipper qw(JT_MITER); use Slic3r::Geometry::Clipper qw(JT_MITER);
sub lines { sub lines {
@ -159,7 +159,7 @@ sub concave_points {
my $self = shift; my $self = shift;
return map $self->[$_], return map $self->[$_],
grep Slic3r::Geometry::angle3points(@$self[$_, $_-1, $_+1]) < PI, grep Slic3r::Geometry::angle3points(@$self[$_, $_-1, $_+1]) < PI - epsilon,
-1 .. ($#$self-1); -1 .. ($#$self-1);
} }

View File

@ -145,6 +145,12 @@ sub slice {
my $self = shift; my $self = shift;
my %params = @_; my %params = @_;
# make sure all layers contain layer region objects for all regions
my $regions_count = $self->print->regions_count;
foreach my $layer (@{ $self->layers }) {
$layer->region($_) for 0 .. ($regions_count-1);
}
# process facets # process facets
for my $region_id (0 .. $#{$self->meshes}) { for my $region_id (0 .. $#{$self->meshes}) {
my $mesh = $self->meshes->[$region_id]; # ignore undef meshes my $mesh = $self->meshes->[$region_id]; # ignore undef meshes
@ -152,8 +158,7 @@ sub slice {
my $apply_lines = sub { my $apply_lines = sub {
my $lines = shift; my $lines = shift;
foreach my $layer_id (keys %$lines) { foreach my $layer_id (keys %$lines) {
my $layerm = $self->layers->[$layer_id]->region($region_id); push @{$self->layers->[$layer_id]->regions->[$region_id]->lines}, @{$lines->{$layer_id}};
push @{$layerm->lines}, @{$lines->{$layer_id}};
} }
}; };
Slic3r::parallelize( Slic3r::parallelize(
@ -192,9 +197,6 @@ sub slice {
pop @{$self->layers} while @{$self->layers} && (!map @{$_->lines}, @{$self->layers->[-1]->regions}); pop @{$self->layers} while @{$self->layers} && (!map @{$_->lines}, @{$self->layers->[-1]->regions});
foreach my $layer (@{ $self->layers }) { foreach my $layer (@{ $self->layers }) {
# make sure all layers contain layer region objects for all regions
$layer->region($_) for 0 .. ($self->print->regions_count-1);
Slic3r::debugf "Making surfaces for layer %d (slice z = %f):\n", Slic3r::debugf "Making surfaces for layer %d (slice z = %f):\n",
$layer->id, unscale $layer->slice_z if $Slic3r::debug; $layer->id, unscale $layer->slice_z if $Slic3r::debug;

View File

@ -27,6 +27,13 @@ sub model {
$facets = [ $facets = [
[0,1,2], [0,2,3], [4,5,6], [4,6,7], [0,4,7], [0,7,1], [1,7,6], [1,6,2], [2,6,5], [2,5,3], [4,0,3], [4,3,5], [0,1,2], [0,2,3], [4,5,6], [4,6,7], [0,4,7], [0,7,1], [1,7,6], [1,6,2], [2,6,5], [2,5,3], [4,0,3], [4,3,5],
], ],
} elsif ($model_name eq 'cube_with_hole') {
$vertices = [
[0,0,0],[0,0,10],[0,20,0],[0,20,10],[20,0,0],[20,0,10],[5,5,0],[15,5,0],[5,15,0],[20,20,0],[15,15,0],[20,20,10],[5,5,10],[5,15,10],[15,5,10],[15,15,10]
];
$facets = [
[0,1,2],[2,1,3],[1,0,4],[5,1,4],[6,7,4],[8,2,9],[0,2,8],[10,8,9],[0,8,6],[0,6,4],[4,7,9],[7,10,9],[2,3,9],[9,3,11],[12,1,5],[13,3,12],[14,12,5],[3,1,12],[11,3,13],[11,15,5],[11,13,15],[15,14,5],[5,4,9],[11,5,9],[8,13,12],[6,8,12],[10,15,13],[8,10,13],[15,10,14],[14,10,7],[14,7,12],[12,7,6]
],
} elsif ($model_name eq 'V') { } elsif ($model_name eq 'V') {
$vertices = [ $vertices = [
[-14,0,20],[-14,15,20],[0,0,0],[0,15,0],[-4,0,20],[-4,15,20],[5,0,7.14286],[10,0,0],[24,0,20],[14,0,20],[10,15,0],[5,15,7.14286],[14,15,20],[24,15,20] [-14,0,20],[-14,15,20],[0,0,0],[0,15,0],[-4,0,20],[-4,15,20],[5,0,7.14286],[10,0,0],[24,0,20],[14,0,20],[10,15,0],[5,15,7.14286],[14,15,20],[24,15,20]

View File

@ -1,6 +1,7 @@
package Slic3r::TriangleMesh; package Slic3r::TriangleMesh;
use Moo; use Moo;
use List::Util qw(reduce min max);
use Slic3r::Geometry qw(X Y Z A B unscale same_point); use Slic3r::Geometry qw(X Y Z A B unscale same_point);
use Slic3r::Geometry::Clipper qw(union_ex); use Slic3r::Geometry::Clipper qw(union_ex);
use Storable; use Storable;
@ -37,6 +38,7 @@ sub analyze {
$self->facets_edges([]); $self->facets_edges([]);
$self->edges_facets([]); $self->edges_facets([]);
my %table = (); # edge_coordinates => edge_id my %table = (); # edge_coordinates => edge_id
my $vertices = $self->vertices; # save method calls
for (my $facet_id = 0; $facet_id <= $#{$self->facets}; $facet_id++) { for (my $facet_id = 0; $facet_id <= $#{$self->facets}; $facet_id++) {
my $facet = $self->facets->[$facet_id]; my $facet = $self->facets->[$facet_id];
@ -46,8 +48,10 @@ sub analyze {
# this is needed to get all intersection lines in a consistent order # this is needed to get all intersection lines in a consistent order
# (external on the right of the line) # (external on the right of the line)
{ {
my @z_order = sort { $self->vertices->[$facet->[$a]][Z] <=> $self->vertices->[$facet->[$b]][Z] } -3..-1; my $lowest_vertex_idx = reduce {
@$facet[-3..-1] = (@$facet[$z_order[0]..-1], @$facet[-3..($z_order[0]-1)]); $vertices->[ $facet->[$a] ][Z] < $vertices->[ $facet->[$b] ][Z] ? $a : $b
} -3 .. -1;
@$facet[-3..-1] = (@$facet[$lowest_vertex_idx..-1], @$facet[-3..($lowest_vertex_idx-1)]);
} }
# ignore the normal if provided # ignore the normal if provided
@ -420,13 +424,11 @@ sub slice_facet {
if $Slic3r::debug; if $Slic3r::debug;
# find the vertical extents of the facet # find the vertical extents of the facet
my ($min_z, $max_z) = (99999999999, -99999999999); my @z = map $_->[Z], @{$self->vertices}[@vertices];
foreach my $vertex (@vertices) { my $min_z = min(@z);
my $vertex_z = $self->vertices->[$vertex][Z]; my $max_z = max(@z);
$min_z = $vertex_z if $vertex_z < $min_z; Slic3r::debugf "z: min = %.0f, max = %.0f\n", $min_z, $max_z
$max_z = $vertex_z if $vertex_z > $max_z; if $Slic3r::debug;
}
Slic3r::debugf "z: min = %.0f, max = %.0f\n", $min_z, $max_z;
if ($max_z == $min_z) { if ($max_z == $min_z) {
Slic3r::debugf "Facet is horizontal; ignoring\n"; Slic3r::debugf "Facet is horizontal; ignoring\n";
@ -435,10 +437,11 @@ sub slice_facet {
# calculate the layer extents # calculate the layer extents
my ($min_layer, $max_layer) = $print_object->get_layer_range($min_z, $max_z); my ($min_layer, $max_layer) = $print_object->get_layer_range($min_z, $max_z);
Slic3r::debugf "layers: min = %s, max = %s\n", $min_layer, $max_layer; Slic3r::debugf "layers: min = %s, max = %s\n", $min_layer, $max_layer
if $Slic3r::debug;
my $lines = {}; # layer_id => [ lines ] my $lines = {}; # layer_id => [ lines ]
for (my $layer_id = $min_layer; $layer_id <= $max_layer; $layer_id++) { for my $layer_id ($min_layer .. $max_layer) {
my $layer = $print_object->layers->[$layer_id]; my $layer = $print_object->layers->[$layer_id];
$lines->{$layer_id} ||= []; $lines->{$layer_id} ||= [];
push @{ $lines->{$layer_id} }, $self->intersect_facet($facet_id, $layer->slice_z); push @{ $lines->{$layer_id} }, $self->intersect_facet($facet_id, $layer->slice_z);
@ -451,25 +454,27 @@ sub intersect_facet {
my ($facet_id, $z) = @_; my ($facet_id, $z) = @_;
my @vertices_ids = @{$self->facets->[$facet_id]}[-3..-1]; my @vertices_ids = @{$self->facets->[$facet_id]}[-3..-1];
my %vertices = map { $_ => $self->vertices->[$_] } @vertices_ids; # cache vertices
my @edge_ids = @{$self->facets_edges->[$facet_id]}; my @edge_ids = @{$self->facets_edges->[$facet_id]};
my @edge_vertices_ids = $self->_facet_edges($facet_id); my @edge_vertices_ids = $self->_facet_edges($facet_id);
my (@lines, @points, @intersection_points, @points_on_layer) = (); my (@points, @intersection_points, @points_on_layer) = ();
for my $e (0..2) { for my $e (0..2) {
my $edge_id = $edge_ids[$e];
my ($a_id, $b_id) = @{$edge_vertices_ids[$e]}; my ($a_id, $b_id) = @{$edge_vertices_ids[$e]};
my ($a, $b) = map $self->vertices->[$_], ($a_id, $b_id); my ($a, $b) = @vertices{$a_id, $b_id};
#printf "Az = %f, Bz = %f, z = %f\n", $a->[Z], $b->[Z], $z; #printf "Az = %f, Bz = %f, z = %f\n", $a->[Z], $b->[Z], $z;
if ($a->[Z] == $b->[Z] && $a->[Z] == $z) { if ($a->[Z] == $b->[Z] && $a->[Z] == $z) {
# edge is horizontal and belongs to the current layer # edge is horizontal and belongs to the current layer
my $edge_type = (grep $self->vertices->[$_][Z] < $z, @vertices_ids) ? FE_TOP : FE_BOTTOM; my $edge_type = (grep $vertices{$_}[Z] < $z, @vertices_ids) ? FE_TOP : FE_BOTTOM;
if ($edge_type == FE_TOP) { if ($edge_type == FE_TOP) {
($a, $b) = ($b, $a); ($a, $b) = ($b, $a);
($a_id, $b_id) = ($b_id, $a_id); ($a_id, $b_id) = ($b_id, $a_id);
} }
push @lines, pack I_FMT, ( # We assume that this method is never being called for horizontal
# facets, so no other edge is going to be on this layer.
return pack I_FMT, (
$b->[X], $b->[Y], # I_B $b->[X], $b->[Y], # I_B
$a_id, # I_A_ID $a_id, # I_A_ID
$b_id, # I_B_ID $b_id, # I_B_ID
@ -499,14 +504,13 @@ sub intersect_facet {
$b->[X] + ($a->[X] - $b->[X]) * ($z - $b->[Z]) / ($a->[Z] - $b->[Z]), $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]), $b->[Y] + ($a->[Y] - $b->[Y]) * ($z - $b->[Z]) / ($a->[Z] - $b->[Z]),
undef, undef,
$edge_id, $edge_ids[$e],
]; ];
push @intersection_points, $#points; push @intersection_points, $#points;
#print "Intersects at $z!\n"; #print "Intersects at $z!\n";
} }
} }
return @lines if @lines;
if (@points_on_layer == 2 && @intersection_points == 1) { if (@points_on_layer == 2 && @intersection_points == 1) {
$points[ $points_on_layer[1] ] = undef; $points[ $points_on_layer[1] ] = undef;
@points = grep $_, @points; @points = grep $_, @points;

View File

@ -1,4 +1,4 @@
use Test::More tests => 3; use Test::More tests => 5;
use strict; use strict;
use warnings; use warnings;
@ -41,6 +41,37 @@ use Slic3r::Test;
ok !$has_cw_loops, 'all perimeters extruded ccw'; ok !$has_cw_loops, 'all perimeters extruded ccw';
} }
{
$config->set('external_perimeter_speed', 68);
my $print = Slic3r::Test::init_print('cube_with_hole', config => $config);
my $has_cw_loops = my $has_outwards_move = 0;
my $cur_loop;
my %external_loops = (); # print_z => count of external loops
Slic3r::GCode::Reader->new(gcode => Slic3r::Test::gcode($print))->parse(sub {
my ($self, $cmd, $args, $info) = @_;
if ($info->{extruding} && $info->{dist_XY} > 0) {
$cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
} else {
if ($cur_loop) {
$has_cw_loops = 1 if !Slic3r::Geometry::Clipper::is_counter_clockwise($cur_loop);
if ($self->F == $config->external_perimeter_speed*60) {
my $move_dest = [ @$info{qw(new_X new_Y)} ];
$external_loops{$self->Z}++;
$has_outwards_move = 1
if !Slic3r::Polygon->new(@$cur_loop)->encloses_point($move_dest)
? ($external_loops{$self->Z} == 2) # contour should include destination
: ($external_loops{$self->Z} == 1); # hole should not
}
$cur_loop = undef;
}
}
});
ok !$has_cw_loops, 'all perimeters extruded ccw';
ok !$has_outwards_move, 'move inwards after completing external loop';
}
{ {
my $print = Slic3r::Test::init_print('L', config => $config); my $print = Slic3r::Test::init_print('L', config => $config);
my $loop_starts_from_convex_point = 0; my $loop_starts_from_convex_point = 0;

View File

@ -2,7 +2,7 @@ use Test::More;
use strict; use strict;
use warnings; use warnings;
plan tests => 17; plan tests => 16;
BEGIN { BEGIN {
use FindBin; use FindBin;
@ -20,11 +20,13 @@ my @points = ([3, 4], [8, 5], [1, 9]); # XY coordinates of the facet vertices
# the first point of the intersection lines is replaced by -1 because TriangleMesh.pm # the first point of the intersection lines is replaced by -1 because TriangleMesh.pm
# is saving memory and doesn't store point A anymore since it's not actually needed. # is saving memory and doesn't store point A anymore since it's not actually needed.
is_deeply lines(20, 20, 20), [ # We disable this test because intersect_facet() now assumes we never feed a horizontal
[ -1, $points[1] ], # $points[0] # facet to it.
[ -1, $points[2] ], # $points[1] # is_deeply lines(20, 20, 20), [
[ -1, $points[0] ], # $points[2] # [ -1, $points[1] ], # $points[0]
], 'horizontal'; # [ -1, $points[2] ], # $points[1]
# [ -1, $points[0] ], # $points[2]
# ], 'horizontal';
is_deeply lines(22, 20, 20), [ [ -1, $points[2] ] ], 'lower edge on layer'; # $points[1] is_deeply lines(22, 20, 20), [ [ -1, $points[2] ] ], 'lower edge on layer'; # $points[1]
is_deeply lines(20, 20, 22), [ [ -1, $points[1] ] ], 'lower edge on layer'; # $points[0] is_deeply lines(20, 20, 22), [ [ -1, $points[1] ] ], 'lower edge on layer'; # $points[0]