123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- 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;
|