Merge branch 'triffid-duplicate'
This commit is contained in:
commit
82a16ed8ee
7 changed files with 146 additions and 21 deletions
|
@ -193,8 +193,9 @@ The author is Alessandro Ranellucci (me).
|
||||||
Transform options:
|
Transform options:
|
||||||
--scale Factor for scaling input object (default: 1)
|
--scale Factor for scaling input object (default: 1)
|
||||||
--rotate Rotation angle in degrees (0-360, default: 0)
|
--rotate Rotation angle in degrees (0-360, default: 0)
|
||||||
--duplicate-x Number of items along X axis (1+, default: 1)
|
--duplicate Number of items with auto-arrange (1+, default: 1)
|
||||||
--duplicate-y Number of items along Y axis (1+, default: 1)
|
--duplicate-x Number of items along X axis for manual arrangement (1+, default: 1)
|
||||||
|
--duplicate-y Number of items along Y axis for manual arrangement (1+, default: 1)
|
||||||
--duplicate-distance Distance in mm between copies (default: 6)
|
--duplicate-distance Distance in mm between copies (default: 6)
|
||||||
|
|
||||||
Miscellaneous options:
|
Miscellaneous options:
|
||||||
|
|
|
@ -138,6 +138,7 @@ our $skirt_height = 1; # layers
|
||||||
# transform options
|
# transform options
|
||||||
our $scale = 1;
|
our $scale = 1;
|
||||||
our $rotate = 0;
|
our $rotate = 0;
|
||||||
|
our $duplicate = 1;
|
||||||
our $duplicate_x = 1;
|
our $duplicate_x = 1;
|
||||||
our $duplicate_y = 1;
|
our $duplicate_y = 1;
|
||||||
our $duplicate_distance = 6; # mm
|
our $duplicate_distance = 6; # mm
|
||||||
|
|
|
@ -10,7 +10,7 @@ our $Options = {
|
||||||
# miscellaneous options
|
# miscellaneous options
|
||||||
'notes' => {
|
'notes' => {
|
||||||
label => 'Configuration notes',
|
label => 'Configuration notes',
|
||||||
cli => 'notes=s',
|
cli => 'notes=s',
|
||||||
type => 's',
|
type => 's',
|
||||||
multiline => 1,
|
multiline => 1,
|
||||||
width => 350,
|
width => 350,
|
||||||
|
@ -392,6 +392,11 @@ our $Options = {
|
||||||
cli => 'rotate=i',
|
cli => 'rotate=i',
|
||||||
type => 'i',
|
type => 'i',
|
||||||
},
|
},
|
||||||
|
'duplicate' => {
|
||||||
|
label => 'Copies (auto arrange)',
|
||||||
|
cli => 'duplicate=i',
|
||||||
|
type => 'i',
|
||||||
|
},
|
||||||
'duplicate_x' => {
|
'duplicate_x' => {
|
||||||
label => 'Copies along X',
|
label => 'Copies along X',
|
||||||
cli => 'duplicate-x=i',
|
cli => 'duplicate-x=i',
|
||||||
|
@ -599,6 +604,10 @@ sub validate {
|
||||||
die "Invalid value for --scale\n"
|
die "Invalid value for --scale\n"
|
||||||
if $Slic3r::scale <= 0;
|
if $Slic3r::scale <= 0;
|
||||||
|
|
||||||
|
# --duplicate
|
||||||
|
die "Invalid value for --duplicate\n"
|
||||||
|
if $Slic3r::duplicate < 1;
|
||||||
|
|
||||||
# --duplicate-x
|
# --duplicate-x
|
||||||
die "Invalid value for --duplicate-x\n"
|
die "Invalid value for --duplicate-x\n"
|
||||||
if $Slic3r::duplicate_x < 1;
|
if $Slic3r::duplicate_x < 1;
|
||||||
|
@ -606,6 +615,11 @@ sub validate {
|
||||||
# --duplicate-y
|
# --duplicate-y
|
||||||
die "Invalid value for --duplicate-y\n"
|
die "Invalid value for --duplicate-y\n"
|
||||||
if $Slic3r::duplicate_y < 1;
|
if $Slic3r::duplicate_y < 1;
|
||||||
|
|
||||||
|
# reflect actual quantity in 'duplicate' setting for use with output-filename-format, ie both --duplicate 15 and --duplicate-x 3 --duplicate-y 5 will make an appropriate filename
|
||||||
|
if ($Slic3r::duplicate == 1 && (($Slic3r::duplicate_x > 1) || ($Slic3r::duplicate_y > 1))) {
|
||||||
|
$Slic3r::duplicate = $Slic3r::duplicate_x * $Slic3r::duplicate_y;
|
||||||
|
}
|
||||||
|
|
||||||
# --duplicate-distance
|
# --duplicate-distance
|
||||||
die "Invalid value for --duplicate-distance\n"
|
die "Invalid value for --duplicate-distance\n"
|
||||||
|
@ -619,8 +633,8 @@ sub validate {
|
||||||
die "Invalid value for --bridge-flow-ratio\n"
|
die "Invalid value for --bridge-flow-ratio\n"
|
||||||
if $Slic3r::bridge_flow_ratio <= 0;
|
if $Slic3r::bridge_flow_ratio <= 0;
|
||||||
|
|
||||||
$Slic3r::first_layer_temperature //= $Slic3r::temperature; #/
|
$Slic3r::first_layer_temperature //= $Slic3r::temperature; #/
|
||||||
$Slic3r::first_layer_bed_temperature //= $Slic3r::bed_temperature; #/
|
$Slic3r::first_layer_bed_temperature //= $Slic3r::bed_temperature; #/
|
||||||
|
|
||||||
# G-code flavors
|
# G-code flavors
|
||||||
$Slic3r::extrusion_axis = 'A' if $Slic3r::gcode_flavor eq 'mach3';
|
$Slic3r::extrusion_axis = 'A' if $Slic3r::gcode_flavor eq 'mach3';
|
||||||
|
|
|
@ -60,7 +60,7 @@ sub new {
|
||||||
},
|
},
|
||||||
transform => {
|
transform => {
|
||||||
title => 'Transform',
|
title => 'Transform',
|
||||||
options => [qw(scale rotate duplicate_x duplicate_y duplicate_distance)],
|
options => [qw(scale rotate duplicate duplicate_x duplicate_y duplicate_distance)],
|
||||||
},
|
},
|
||||||
gcode => {
|
gcode => {
|
||||||
title => 'Custom G-code',
|
title => 'Custom G-code',
|
||||||
|
|
|
@ -157,17 +157,125 @@ sub BUILD {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
my $dist = scale $Slic3r::duplicate_distance;
|
my $dist = scale $Slic3r::duplicate_distance;
|
||||||
$self->total_x_length($self->x_length * $Slic3r::duplicate_x + $dist * ($Slic3r::duplicate_x - 1));
|
|
||||||
$self->total_y_length($self->y_length * $Slic3r::duplicate_y + $dist * ($Slic3r::duplicate_y - 1));
|
if ($Slic3r::duplicate_x > 1 || $Slic3r::duplicate_y > 1) {
|
||||||
|
$self->total_x_length($self->x_length * $Slic3r::duplicate_x + $dist * ($Slic3r::duplicate_x - 1));
|
||||||
# generate offsets for copies
|
$self->total_y_length($self->y_length * $Slic3r::duplicate_y + $dist * ($Slic3r::duplicate_y - 1));
|
||||||
for my $x_copy (1..$Slic3r::duplicate_x) {
|
|
||||||
for my $y_copy (1..$Slic3r::duplicate_y) {
|
# generate offsets for copies
|
||||||
push @{$self->copies}, [
|
for my $x_copy (1..$Slic3r::duplicate_x) {
|
||||||
($self->x_length + scale $Slic3r::duplicate_distance) * ($x_copy-1),
|
for my $y_copy (1..$Slic3r::duplicate_y) {
|
||||||
($self->y_length + scale $Slic3r::duplicate_distance) * ($y_copy-1),
|
push @{$self->copies}, [
|
||||||
];
|
($self->x_length + $dist) * ($x_copy-1),
|
||||||
|
($self->y_length + $dist) * ($y_copy-1),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} elsif ($Slic3r::duplicate > 1) {
|
||||||
|
my $linint = sub {
|
||||||
|
my ($value, $oldmin, $oldmax, $newmin, $newmax) = @_;
|
||||||
|
return ($value - $oldmin) * ($newmax - $newmin) / ($oldmax - $oldmin) + $newmin;
|
||||||
|
};
|
||||||
|
|
||||||
|
# use center location to determine print area. assume X200 Y200 if center is 0,0
|
||||||
|
# TODO: add user configuration for bed area with new gui
|
||||||
|
my $printx = $Slic3r::print_center->[X] * 2 || 200;
|
||||||
|
my $printy = $Slic3r::print_center->[Y] * 2 || 200;
|
||||||
|
|
||||||
|
# use actual part size plus separation distance (half on each side) in spacing algorithm
|
||||||
|
my $partx = unscale($self->x_length) + $Slic3r::duplicate_distance;
|
||||||
|
my $party = unscale($self->y_length) + $Slic3r::duplicate_distance;
|
||||||
|
|
||||||
|
# this is how many cells we have available into which to put parts
|
||||||
|
my $cellw = int($printx / $partx);
|
||||||
|
my $cellh = int($printy / $party);
|
||||||
|
die "$Slic3r::duplicate parts won't fit in your print area!\n" if $Slic3r::duplicate > ($cellw * $cellh);
|
||||||
|
|
||||||
|
# width and height of space used by cells
|
||||||
|
my $w = $cellw * $partx;
|
||||||
|
my $h = $cellh * $party;
|
||||||
|
|
||||||
|
# left and right border positions of space used by cells
|
||||||
|
my $l = ($printx - $w) / 2;
|
||||||
|
my $r = $l + $w;
|
||||||
|
|
||||||
|
# top and bottom border positions
|
||||||
|
my $t = ($printy - $h) / 2;
|
||||||
|
my $b = $t + $h;
|
||||||
|
|
||||||
|
# list of cells, sorted by distance from center
|
||||||
|
my @cellsorder;
|
||||||
|
|
||||||
|
# work out distance for all cells, sort into list
|
||||||
|
for my $i (0..$cellw-1) {
|
||||||
|
for my $j (0..$cellh-1) {
|
||||||
|
my $cx = $linint->($i + 0.5, 0, $cellw, $l, $r);
|
||||||
|
my $cy = $linint->($j + 0.5, 0, $cellh, $t, $b);
|
||||||
|
|
||||||
|
my $xd = abs(($printx / 2) - $cx);
|
||||||
|
my $yd = abs(($printy / 2) - $cy);
|
||||||
|
|
||||||
|
my $c = {
|
||||||
|
location => [$cx, $cy],
|
||||||
|
index => [$i, $j],
|
||||||
|
distance => $xd * $xd + $yd * $yd - abs(($cellw / 2) - ($i + 0.5)),
|
||||||
|
};
|
||||||
|
|
||||||
|
BINARYINSERTIONSORT: {
|
||||||
|
my $index = $c->{distance};
|
||||||
|
my $low = 0;
|
||||||
|
my $high = @cellsorder;
|
||||||
|
while ($low < $high) {
|
||||||
|
my $mid = ($low + (($high - $low) / 2)) | 0;
|
||||||
|
my $midval = $cellsorder[$mid]->[0];
|
||||||
|
|
||||||
|
if ($midval < $index) {
|
||||||
|
$low = $mid + 1;
|
||||||
|
} elsif ($midval > $index) {
|
||||||
|
$high = $mid;
|
||||||
|
} else {
|
||||||
|
splice @cellsorder, $mid, 0, [$index, $c];
|
||||||
|
last BINARYINSERTIONSORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
splice @cellsorder, $low, 0, [$index, $c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# the extents of cells actually used by objects
|
||||||
|
my ($lx, $ty, $rx, $by) = (0, 0, 0, 0);
|
||||||
|
|
||||||
|
# now find cells actually used by objects, map out the extents so we can position correctly
|
||||||
|
for my $i (1..$Slic3r::duplicate) {
|
||||||
|
my $c = $cellsorder[$i - 1];
|
||||||
|
my $cx = $c->[1]->{index}->[0];
|
||||||
|
my $cy = $c->[1]->{index}->[1];
|
||||||
|
if ($i == 1) {
|
||||||
|
$lx = $rx = $cx;
|
||||||
|
$ty = $by = $cy;
|
||||||
|
} else {
|
||||||
|
$rx = $cx if $cx > $rx;
|
||||||
|
$lx = $cx if $cx < $lx;
|
||||||
|
$by = $cy if $cy > $by;
|
||||||
|
$ty = $cy if $cy < $ty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# now we actually place objects into cells, positioned such that the left and bottom borders are at 0
|
||||||
|
for my $i (1..$Slic3r::duplicate) {
|
||||||
|
my $c = shift @cellsorder;
|
||||||
|
my $cx = $c->[1]->{index}->[0] - $lx;
|
||||||
|
my $cy = $c->[1]->{index}->[1] - $ty;
|
||||||
|
|
||||||
|
push @{$self->copies}, [scale($cx * $partx - (unscale($self->x_length) / 2)), scale($cy * $party - (unscale($self->y_length) / 2))];
|
||||||
|
}
|
||||||
|
# save size of area used
|
||||||
|
$self->total_x_length(scale(($rx - $lx) * $partx));
|
||||||
|
$self->total_y_length(scale(($by - $ty) * $party));
|
||||||
|
} else {
|
||||||
|
$self->total_x_length($self->x_length);
|
||||||
|
$self->total_y_length($self->y_length);
|
||||||
|
push @{$self->copies}, [0, 0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,9 +190,9 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
print $fh <<"EOF";
|
print $fh <<"EOF";
|
||||||
<!--
|
<!--
|
||||||
Generated using Slic3r $Slic3r::VERSION
|
Generated using Slic3r $Slic3r::VERSION
|
||||||
http://slic3r.org/
|
http://slic3r.org/
|
||||||
-->
|
-->
|
||||||
</svg>
|
</svg>
|
||||||
EOF
|
EOF
|
||||||
|
|
|
@ -216,8 +216,9 @@ Usage: slic3r.pl [ OPTIONS ] file.stl
|
||||||
Transform options:
|
Transform options:
|
||||||
--scale Factor for scaling input object (default: $Slic3r::scale)
|
--scale Factor for scaling input object (default: $Slic3r::scale)
|
||||||
--rotate Rotation angle in degrees (0-360, default: $Slic3r::rotate)
|
--rotate Rotation angle in degrees (0-360, default: $Slic3r::rotate)
|
||||||
--duplicate-x Number of items along X axis (1+, default: $Slic3r::duplicate_x)
|
--duplicate Number of items with auto-arrange (1+, default: $Slic3r::duplicate)
|
||||||
--duplicate-y Number of items along Y axis (1+, default: $Slic3r::duplicate_y)
|
--duplicate-x Number of items along X axis for manual arrangement (1+, default: $Slic3r::duplicate_x)
|
||||||
|
--duplicate-y Number of items along Y axis for manual arrangement (1+, default: $Slic3r::duplicate_y)
|
||||||
--duplicate-distance Distance in mm between copies (default: $Slic3r::duplicate_distance)
|
--duplicate-distance Distance in mm between copies (default: $Slic3r::duplicate_distance)
|
||||||
|
|
||||||
Miscellaneous options:
|
Miscellaneous options:
|
||||||
|
|
Loading…
Add table
Reference in a new issue