mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 15:44:12 -06:00
Large memory saving and speed boost
This commit is contained in:
parent
61e257388a
commit
a165ad4ecb
5 changed files with 68 additions and 77 deletions
1
MANIFEST
1
MANIFEST
|
@ -37,7 +37,6 @@ lib/Slic3r/Print/Object.pm
|
||||||
lib/Slic3r/Surface.pm
|
lib/Slic3r/Surface.pm
|
||||||
lib/Slic3r/SVG.pm
|
lib/Slic3r/SVG.pm
|
||||||
lib/Slic3r/TriangleMesh.pm
|
lib/Slic3r/TriangleMesh.pm
|
||||||
lib/Slic3r/TriangleMesh/IntersectionLine.pm
|
|
||||||
MANIFEST This list of files
|
MANIFEST This list of files
|
||||||
README.markdown
|
README.markdown
|
||||||
slic3r.pl
|
slic3r.pl
|
||||||
|
|
|
@ -35,7 +35,6 @@ use Slic3r::Print;
|
||||||
use Slic3r::Print::Object;
|
use Slic3r::Print::Object;
|
||||||
use Slic3r::Surface;
|
use Slic3r::Surface;
|
||||||
use Slic3r::TriangleMesh;
|
use Slic3r::TriangleMesh;
|
||||||
use Slic3r::TriangleMesh::IntersectionLine;
|
|
||||||
|
|
||||||
our $have_threads = $Config{useithreads} && eval "use threads; use Thread::Queue; 1";
|
our $have_threads = $Config{useithreads} && eval "use threads; use Thread::Queue; 1";
|
||||||
our $threads = $have_threads ? 4 : undef;
|
our $threads = $have_threads ? 4 : undef;
|
||||||
|
|
|
@ -18,7 +18,7 @@ has 'slicing_errors' => (is => 'rw');
|
||||||
# these need to be merged in continuos (closed) polylines
|
# these need to be merged in continuos (closed) polylines
|
||||||
has 'lines' => (
|
has 'lines' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
#isa => 'ArrayRef[Slic3r::TriangleMesh::IntersectionLine]',
|
#isa => 'ArrayRef[ArrayRef]',
|
||||||
default => sub { [] },
|
default => sub { [] },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,17 @@ has 'edges_facets' => (is => 'ro', default => sub { [] }); # id => [ $f1_id, $f
|
||||||
use constant MIN => 0;
|
use constant MIN => 0;
|
||||||
use constant MAX => 1;
|
use constant MAX => 1;
|
||||||
|
|
||||||
|
use constant I_B => 0;
|
||||||
|
use constant I_A_ID => 1;
|
||||||
|
use constant I_B_ID => 2;
|
||||||
|
use constant I_FACET_INDEX => 3;
|
||||||
|
use constant I_PREV_FACET_INDEX => 4;
|
||||||
|
use constant I_NEXT_FACET_INDEX => 5;
|
||||||
|
use constant I_FACET_EDGE => 6;
|
||||||
|
|
||||||
|
use constant FE_TOP => 0;
|
||||||
|
use constant FE_BOTTOM => 1;
|
||||||
|
|
||||||
# always make sure BUILD is idempotent
|
# always make sure BUILD is idempotent
|
||||||
sub BUILD {
|
sub BUILD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
@ -133,11 +144,11 @@ sub make_loops {
|
||||||
# remove tangent edges
|
# remove tangent edges
|
||||||
{
|
{
|
||||||
for (my $i = 0; $i <= $#lines; $i++) {
|
for (my $i = 0; $i <= $#lines; $i++) {
|
||||||
next unless defined $lines[$i] && $lines[$i]->facet_edge;
|
next unless defined $lines[$i] && $lines[$i]->[I_FACET_EDGE];
|
||||||
# if the line is a facet edge, find another facet edge
|
# if the line is a facet edge, find another facet edge
|
||||||
# having the same endpoints but in reverse order
|
# having the same endpoints but in reverse order
|
||||||
for (my $j = $i+1; $j <= $#lines; $j++) {
|
for (my $j = $i+1; $j <= $#lines; $j++) {
|
||||||
next unless defined $lines[$j] && $lines[$j]->facet_edge;
|
next unless defined $lines[$j] && $lines[$j]->[I_FACET_EDGE];
|
||||||
|
|
||||||
# are these facets adjacent? (sharing a common edge on this layer)
|
# are these facets adjacent? (sharing a common edge on this layer)
|
||||||
if ($lines[$i]->a_id == $lines[$j]->b_id && $lines[$i]->b_id == $lines[$j]->a_id) {
|
if ($lines[$i]->a_id == $lines[$j]->b_id && $lines[$i]->b_id == $lines[$j]->a_id) {
|
||||||
|
@ -145,7 +156,7 @@ sub make_loops {
|
||||||
# if they are both oriented upwards or downwards (like a 'V')
|
# if they are both oriented upwards or downwards (like a 'V')
|
||||||
# then we can remove both edges from this layer since it won't
|
# then we can remove both edges from this layer since it won't
|
||||||
# affect the sliced shape
|
# affect the sliced shape
|
||||||
if ($lines[$j]->facet_edge eq $lines[$i]->facet_edge) {
|
if ($lines[$j]->[I_FACET_EDGE] eq $lines[$i]->[I_FACET_EDGE]) {
|
||||||
$lines[$i] = undef;
|
$lines[$i] = undef;
|
||||||
$lines[$j] = undef;
|
$lines[$j] = undef;
|
||||||
last;
|
last;
|
||||||
|
@ -154,7 +165,7 @@ sub make_loops {
|
||||||
# if one of them is oriented upwards and the other is oriented
|
# if one of them is oriented upwards and the other is oriented
|
||||||
# downwards, let's only keep one of them (it doesn't matter which
|
# downwards, let's only keep one of them (it doesn't matter which
|
||||||
# one since all 'top' lines were reversed at slicing)
|
# one since all 'top' lines were reversed at slicing)
|
||||||
if ($lines[$i]->facet_edge eq 'top' && $lines[$j]->facet_edge eq 'bottom') {
|
if ($lines[$i]->[I_FACET_EDGE] eq FE_TOP && $lines[$j]->[I_FACET_EDGE] eq FE_BOTTOM) {
|
||||||
$lines[$j] = undef;
|
$lines[$j] = undef;
|
||||||
last;
|
last;
|
||||||
}
|
}
|
||||||
|
@ -170,25 +181,25 @@ sub make_loops {
|
||||||
my %prev_count = (); # how many lines have the same prev_facet_index
|
my %prev_count = (); # how many lines have the same prev_facet_index
|
||||||
my %a_count = (); # how many lines have the same a_id
|
my %a_count = (); # how many lines have the same a_id
|
||||||
foreach my $line (@lines) {
|
foreach my $line (@lines) {
|
||||||
if (defined $line->prev_facet_index) {
|
if (defined $line->[I_PREV_FACET_INDEX]) {
|
||||||
$prev_count{$line->prev_facet_index}++;
|
$prev_count{$line->[I_PREV_FACET_INDEX]}++;
|
||||||
}
|
}
|
||||||
if (defined $line->a_id) {
|
if (defined $line->[I_A_ID]) {
|
||||||
$a_count{$line->a_id}++;
|
$a_count{$line->[I_A_ID]}++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach my $point_id (grep $a_count{$_} > 1, keys %a_count) {
|
foreach my $point_id (grep $a_count{$_} > 1, keys %a_count) {
|
||||||
my @lines_starting_here = grep defined $_->a_id && $_->a_id == $point_id, @lines;
|
my @lines_starting_here = grep defined $_->[I_A_ID] && $_->[I_A_ID] == $point_id, @lines;
|
||||||
Slic3r::debugf "%d lines start at point %d\n", scalar(@lines_starting_here), $point_id;
|
Slic3r::debugf "%d lines start at point %d\n", scalar(@lines_starting_here), $point_id;
|
||||||
|
|
||||||
# if two lines start at this point, one being a 'top' facet edge and the other being a 'bottom' one,
|
# if two lines start at this point, one being a 'top' facet edge and the other being a 'bottom' one,
|
||||||
# then remove the top one and those following it (removing the top or the bottom one is an arbitrary
|
# then remove the top one and those following it (removing the top or the bottom one is an arbitrary
|
||||||
# choice)
|
# choice)
|
||||||
if (@lines_starting_here == 2 && join(',', sort map $_->facet_edge, @lines_starting_here) eq 'bottom,top') {
|
if (@lines_starting_here == 2 && join('', sort map $_->[I_FACET_EDGE], @lines_starting_here) eq FE_BOTTOM.FE_TOP) {
|
||||||
my @to_remove = grep $_->facet_edge eq 'top', @lines_starting_here;
|
my @to_remove = grep $_->[I_FACET_EDGE] eq FE_TOP, @lines_starting_here;
|
||||||
while (!grep defined $_->b_id && $_->b_id == $to_remove[-1]->b_id && $_ ne $to_remove[-1], @lines) {
|
while (!grep defined $_->[I_B_ID] && $_->[I_B_ID] == $to_remove[-1]->[I_B_ID] && $_ ne $to_remove[-1], @lines) {
|
||||||
push @to_remove, grep defined $_->a_id && $_->a_id == $to_remove[-1]->b_id, @lines;
|
push @to_remove, grep defined $_->[I_A_ID] && $_->[I_A_ID] == $to_remove[-1]->[I_B_ID], @lines;
|
||||||
}
|
}
|
||||||
my %to_remove = map {$_ => 1} @to_remove;
|
my %to_remove = map {$_ => 1} @to_remove;
|
||||||
@lines = grep !$to_remove{$_}, @lines;
|
@lines = grep !$to_remove{$_}, @lines;
|
||||||
|
@ -197,8 +208,8 @@ sub make_loops {
|
||||||
if (0) {
|
if (0) {
|
||||||
require "Slic3r/SVG.pm";
|
require "Slic3r/SVG.pm";
|
||||||
Slic3r::SVG::output(undef, "same_point.svg",
|
Slic3r::SVG::output(undef, "same_point.svg",
|
||||||
lines => [ map $_->line, grep !$_->facet_edge, @lines ],
|
lines => [ map $_->line, grep !$_->[I_FACET_EDGE], @lines ],
|
||||||
red_lines => [ map $_->line, grep $_->facet_edge, @lines ],
|
red_lines => [ map $_->line, grep $_->[I_FACET_EDGE], @lines ],
|
||||||
points => [ $self->vertices->[$point_id] ],
|
points => [ $self->vertices->[$point_id] ],
|
||||||
no_arrows => 0,
|
no_arrows => 0,
|
||||||
);
|
);
|
||||||
|
@ -207,11 +218,11 @@ sub make_loops {
|
||||||
}
|
}
|
||||||
|
|
||||||
# optimization: build indexes of lines
|
# optimization: build indexes of lines
|
||||||
my %by_facet_index = map { $lines[$_]->facet_index => $_ }
|
my %by_facet_index = map { $lines[$_]->[I_FACET_INDEX] => $_ }
|
||||||
grep defined $lines[$_]->facet_index,
|
grep defined $lines[$_]->[I_FACET_INDEX],
|
||||||
(0..$#lines);
|
(0..$#lines);
|
||||||
my %by_a_id = map { $lines[$_]->a_id => $_ }
|
my %by_a_id = map { $lines[$_]->[I_A_ID] => $_ }
|
||||||
grep defined $lines[$_]->a_id,
|
grep defined $lines[$_]->[I_A_ID],
|
||||||
(0..$#lines);
|
(0..$#lines);
|
||||||
|
|
||||||
my (@polygons, %visited_lines) = ();
|
my (@polygons, %visited_lines) = ();
|
||||||
|
@ -219,14 +230,14 @@ sub make_loops {
|
||||||
my $line = $lines[$i];
|
my $line = $lines[$i];
|
||||||
next if $visited_lines{$line};
|
next if $visited_lines{$line};
|
||||||
my @points = ();
|
my @points = ();
|
||||||
my $first_facet_index = $line->facet_index;
|
my $first_facet_index = $line->[I_FACET_INDEX];
|
||||||
|
|
||||||
do {
|
do {
|
||||||
my $next_line;
|
my $next_line;
|
||||||
if (defined $line->next_facet_index && exists $by_facet_index{$line->next_facet_index}) {
|
if (defined $line->[I_NEXT_FACET_INDEX] && exists $by_facet_index{$line->[I_NEXT_FACET_INDEX]}) {
|
||||||
$next_line = $lines[$by_facet_index{$line->next_facet_index}];
|
$next_line = $lines[$by_facet_index{$line->[I_NEXT_FACET_INDEX]}];
|
||||||
} elsif (defined $line->b_id && exists $by_a_id{$line->b_id}) {
|
} elsif (defined $line->[I_B_ID] && exists $by_a_id{$line->[I_B_ID]}) {
|
||||||
$next_line = $lines[$by_a_id{$line->b_id}];
|
$next_line = $lines[$by_a_id{$line->[I_B_ID]}];
|
||||||
} else {
|
} else {
|
||||||
Slic3r::debugf " line has no next_facet_index or b_id\n";
|
Slic3r::debugf " line has no next_facet_index or b_id\n";
|
||||||
$layer->slicing_errors(1);
|
$layer->slicing_errors(1);
|
||||||
|
@ -237,20 +248,20 @@ sub make_loops {
|
||||||
Slic3r::debugf " failed to close this loop\n";
|
Slic3r::debugf " failed to close this loop\n";
|
||||||
$layer->slicing_errors(1);
|
$layer->slicing_errors(1);
|
||||||
next CYCLE;
|
next CYCLE;
|
||||||
} elsif (defined $next_line->prev_facet_index && $next_line->prev_facet_index != $line->facet_index) {
|
} elsif (defined $next_line->[I_PREV_FACET_INDEX] && $next_line->[I_PREV_FACET_INDEX] != $line->[I_FACET_INDEX]) {
|
||||||
Slic3r::debugf " wrong prev_facet_index\n";
|
Slic3r::debugf " wrong prev_facet_index\n";
|
||||||
$layer->slicing_errors(1);
|
$layer->slicing_errors(1);
|
||||||
next CYCLE;
|
next CYCLE;
|
||||||
} elsif (defined $next_line->a_id && $next_line->a_id != $line->b_id) {
|
} elsif (defined $next_line->[I_A_ID] && $next_line->[I_A_ID] != $line->b_id) {
|
||||||
Slic3r::debugf " wrong a_id\n";
|
Slic3r::debugf " wrong a_id\n";
|
||||||
$layer->slicing_errors(1);
|
$layer->slicing_errors(1);
|
||||||
next CYCLE;
|
next CYCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
push @points, $next_line->b;
|
push @points, $next_line->[I_B];
|
||||||
$visited_lines{$next_line} = 1;
|
$visited_lines{$next_line} = 1;
|
||||||
$line = $next_line;
|
$line = $next_line;
|
||||||
} while ($first_facet_index != $line->facet_index);
|
} while ($first_facet_index != $line->[I_FACET_INDEX]);
|
||||||
|
|
||||||
push @polygons, Slic3r::Polygon->new(@points);
|
push @polygons, Slic3r::Polygon->new(@points);
|
||||||
Slic3r::debugf " Discovered %s polygon of %d points\n",
|
Slic3r::debugf " Discovered %s polygon of %d points\n",
|
||||||
|
@ -400,19 +411,23 @@ sub intersect_facet {
|
||||||
|
|
||||||
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) ? 'top' : 'bottom';
|
my $edge_type = (grep $self->vertices->[$_][Z] < $z, @vertices_ids) ? FE_TOP : FE_BOTTOM;
|
||||||
if ($edge_type eq 'top') {
|
if ($edge_type eq 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, Slic3r::TriangleMesh::IntersectionLine->new(
|
push @lines, [
|
||||||
a => [$a->[X], $a->[Y]],
|
[$b->[X], $b->[Y]], # I_B
|
||||||
b => [$b->[X], $b->[Y]],
|
$a_id, # I_A_ID
|
||||||
a_id => $a_id,
|
$b_id, # I_B_ID
|
||||||
b_id => $b_id,
|
$facet_id, # I_FACET_INDEX
|
||||||
facet_edge => $edge_type,
|
undef, # I_PREV_FACET_INDEX
|
||||||
facet_index => $facet_id,
|
undef, # I_NEXT_FACET_INDEX
|
||||||
);
|
$edge_type, # I_FACET_EDGE
|
||||||
|
|
||||||
|
# Unused data:
|
||||||
|
# a => [$a->[X], $a->[Y]],
|
||||||
|
];
|
||||||
#print "Horizontal edge at $z!\n";
|
#print "Horizontal edge at $z!\n";
|
||||||
|
|
||||||
} elsif ($a->[Z] == $z) {
|
} elsif ($a->[Z] == $z) {
|
||||||
|
@ -461,17 +476,20 @@ sub intersect_facet {
|
||||||
$next_facet_index = +(grep $_ != $facet_id, @{$self->edges_facets->[$points[A][3]]})[0]
|
$next_facet_index = +(grep $_ != $facet_id, @{$self->edges_facets->[$points[A][3]]})[0]
|
||||||
if defined $points[A][3];
|
if defined $points[A][3];
|
||||||
|
|
||||||
return Slic3r::TriangleMesh::IntersectionLine->new(
|
return [
|
||||||
a => [$points[B][X], $points[B][Y]],
|
[$points[A][X], $points[A][Y]], # I_B
|
||||||
b => [$points[A][X], $points[A][Y]],
|
$points[B][2], # I_A_ID
|
||||||
a_id => $points[B][2],
|
$points[A][2], # I_B_ID
|
||||||
b_id => $points[A][2],
|
$facet_id, # I_FACET_INDEX
|
||||||
facet_index => $facet_id,
|
$prev_facet_index, # I_PREV_FACET_INDEX
|
||||||
prev_edge_id => $points[B][3],
|
$next_facet_index, # I_NEXT_FACET_INDEX
|
||||||
next_edge_id => $points[A][3],
|
undef, # I_FACET_EDGE
|
||||||
prev_facet_index => $prev_facet_index,
|
|
||||||
next_facet_index => $next_facet_index,
|
# Unused data:
|
||||||
);
|
# a => [$points[B][X], $points[B][Y]],
|
||||||
|
# prev_edge_id => $points[B][3],
|
||||||
|
# next_edge_id => $points[A][3],
|
||||||
|
];
|
||||||
#printf " intersection points at z = %f: %f,%f - %f,%f\n", $z, map @$_, @intersection_points;
|
#printf " intersection points at z = %f: %f,%f - %f,%f\n", $z, map @$_, @intersection_points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package Slic3r::TriangleMesh::IntersectionLine;
|
|
||||||
use Moo;
|
|
||||||
|
|
||||||
has 'a' => (is => 'ro', required => 1);
|
|
||||||
has 'b' => (is => 'ro', required => 1);
|
|
||||||
has 'a_id' => (is => 'ro', required => 1);
|
|
||||||
has 'b_id' => (is => 'ro', required => 1);
|
|
||||||
has 'facet_index' => (is => 'ro', required => 1);
|
|
||||||
has 'prev_facet_index' => (is => 'ro', required => 0);
|
|
||||||
has 'next_facet_index' => (is => 'ro', required => 0);
|
|
||||||
has 'prev_edge_id' => (is => 'ro', required => 0);
|
|
||||||
has 'next_edge_id' => (is => 'ro', required => 0);
|
|
||||||
has 'facet_edge' => (is => 'ro', default => sub {0});
|
|
||||||
|
|
||||||
sub points {
|
|
||||||
my $self = shift;
|
|
||||||
return [$self->a, $self->b];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub line {
|
|
||||||
my $self = shift;
|
|
||||||
return Slic3r::Line->new($self->a, $self->b);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
Loading…
Add table
Add a link
Reference in a new issue