PrusaSlicer-NonPlainar/lib/Slic3r/SVG.pm

143 lines
4.1 KiB
Perl

package Slic3r::SVG;
use strict;
use warnings;
use SVG;
use constant X => 0;
use constant Y => 1;
our $filltype = 'evenodd';
sub factor {
return &Slic3r::SCALING_FACTOR * 10;
}
sub svg {
my $svg = SVG->new(width => 200 * 10, height => 200 * 10);
my $marker_end = $svg->marker(
id => "endArrow",
viewBox => "0 0 10 10",
refX => "1",
refY => "5",
markerUnits => "strokeWidth",
orient => "auto",
markerWidth => "10",
markerHeight => "8",
);
$marker_end->polyline(
points => "0,0 10,5 0,10 1,5",
fill => "darkblue",
);
return $svg;
}
sub output {
my ($filename, @things) = @_;
my $svg = svg();
my $arrows = 1;
while (my $type = shift @things) {
my $value = shift @things;
if ($type eq 'no_arrows') {
$arrows = 0;
} elsif ($type =~ /^(?:(.+?)_)?expolygons$/) {
my $colour = $1;
$value = [ map $_->pp, @$value ];
my $g = $svg->group(
style => {
'stroke-width' => 0,
'stroke' => $colour || 'black',
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
'fill-type' => $filltype,
},
);
foreach my $expolygon (@$value) {
my $points = join ' ', map "M $_ z", map join(" ", reverse map $_->[0]*factor() . " " . $_->[1]*factor(), @$_), @$expolygon;
$g->path(
d => $points,
);
}
} elsif ($type =~ /^(?:(.+?)_)?(polygon|polyline)s$/) {
my ($colour, $method) = ($1, $2);
$value = [ map $_->pp, @$value ];
my $g = $svg->group(
style => {
'stroke-width' => ($method eq 'polyline') ? 1 : 0,
'stroke' => $colour || 'black',
'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
},
);
foreach my $polygon (@$value) {
my $path = $svg->get_path(
'x' => [ map($_->[X] * factor(), @$polygon) ],
'y' => [ map($_->[Y] * factor(), @$polygon) ],
-type => 'polygon',
);
$g->$method(
%$path,
'marker-end' => !$arrows ? "" : "url(#endArrow)",
);
}
} elsif ($type =~ /^(?:(.+?)_)?points$/) {
my $colour = $1 // 'black';
my $r = $colour eq 'black' ? 1 : 3;
$value = [ map $_->pp, @$value ];
my $g = $svg->group(
style => {
'stroke-width' => 2,
'stroke' => $colour,
'fill' => $colour,
},
);
foreach my $point (@$value) {
$g->circle(
cx => $point->[X] * factor(),
cy => $point->[Y] * factor(),
r => $r,
);
}
} elsif ($type =~ /^(?:(.+?)_)?lines$/) {
my $colour = $1;
$value = [ map $_->pp, @$value ];
my $g = $svg->group(
style => {
'stroke-width' => 2,
},
);
foreach my $line (@$value) {
$g->line(
x1 => $line->[0][X] * factor(),
y1 => $line->[0][Y] * factor(),
x2 => $line->[1][X] * factor(),
y2 => $line->[1][Y] * factor(),
style => {
'stroke' => $colour || 'black',
},
'marker-end' => !$arrows ? "" : "url(#endArrow)",
);
}
}
}
write_svg($svg, $filename);
}
sub write_svg {
my ($svg, $filename) = @_;
Slic3r::open(\my $fh, '>', $filename);
print $fh $svg->xmlify;
close $fh;
printf "SVG written to %s\n", $filename;
}
1;