SVG.pm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package Slic3r::SVG;
  2. use strict;
  3. use warnings;
  4. use SVG;
  5. use constant X => 0;
  6. use constant Y => 1;
  7. sub factor {
  8. return $Slic3r::resolution * 10;
  9. }
  10. sub svg {
  11. my ($print) = @_;
  12. $print ||= Slic3r::Print->new(x_length => 200 / $Slic3r::resolution, y_length => 200 / $Slic3r::resolution);
  13. my $svg = SVG->new(width => $print->max_length * factor(), height => $print->max_length * factor());
  14. my $marker_end = $svg->marker(
  15. id => "endArrow",
  16. viewBox => "0 0 10 10",
  17. refX => "1",
  18. refY => "5",
  19. markerUnits => "strokeWidth",
  20. orient => "auto",
  21. markerWidth => "10",
  22. markerHeight => "8",
  23. );
  24. $marker_end->polyline(
  25. points => "0,0 10,5 0,10 1,5",
  26. fill => "darkblue",
  27. );
  28. return $svg;
  29. }
  30. sub output {
  31. my ($print, $filename, %things) = @_;
  32. my $svg = svg($print);
  33. foreach my $type (qw(polygons polylines white_polygons red_polygons red_polylines)) {
  34. if ($things{$type}) {
  35. my $method = $type =~ /polygons/ ? 'polygon' : 'polyline';
  36. my $g = $svg->group(
  37. style => {
  38. 'stroke-width' => 2,
  39. 'stroke' => $type =~ /red_/ ? 'red' : 'black',
  40. 'fill' => ($type !~ /polygons/ ? 'none' : ($type =~ /red_/ ? 'red' : 'grey')),
  41. },
  42. );
  43. foreach my $polygon (@{$things{$type}}) {
  44. my $path = $svg->get_path(
  45. 'x' => [ map($_->[X] * factor(), @$polygon) ],
  46. 'y' => [ map($_->[Y] * factor(), @$polygon) ],
  47. -type => 'polygon',
  48. );
  49. $g->$method(
  50. %$path,
  51. 'marker-end' => "url(#endArrow)",
  52. );
  53. }
  54. }
  55. }
  56. foreach my $type (qw(points red_points)) {
  57. if ($things{$type}) {
  58. my ($colour, $r) = $type eq 'points' ? ('black', 2) : ('red', 3);
  59. my $g = $svg->group(
  60. style => {
  61. 'stroke-width' => 2,
  62. 'stroke' => $colour,
  63. 'fill' => $colour,
  64. },
  65. );
  66. foreach my $point (@{$things{$type}}) {
  67. $g->circle(
  68. cx => $point->[X] * factor(),
  69. cy => $point->[Y] * factor(),
  70. r => $r,
  71. );
  72. }
  73. }
  74. }
  75. foreach my $type (qw(lines red_lines green_lines)) {
  76. if ($things{$type}) {
  77. my ($colour) = $type =~ /^(red|green)_/;
  78. my $g = $svg->group(
  79. style => {
  80. 'stroke-width' => 2,
  81. },
  82. );
  83. foreach my $line (@{$things{$type}}) {
  84. $g->line(
  85. x1 => $line->[0][X] * factor(),
  86. y1 => $line->[0][Y] * factor(),
  87. x2 => $line->[1][X] * factor(),
  88. y2 => $line->[1][Y] * factor(),
  89. style => {
  90. 'stroke' => $colour || 'black',
  91. },
  92. 'marker-end' => "url(#endArrow)",
  93. );
  94. }
  95. }
  96. }
  97. write_svg($svg, $filename);
  98. }
  99. sub output_points {
  100. my ($print, $filename, $points, $red_points) = @_;
  101. return output($print, $filename, points => $points, red_points => $red_points);
  102. }
  103. sub output_polygons {
  104. my ($print, $filename, $polygons) = @_;
  105. return output($print, $filename, polygons => $polygons);
  106. }
  107. sub output_polylines {
  108. my ($print, $filename, $polylines) = @_;
  109. return output($print, $filename, polylines => $polylines);
  110. }
  111. sub output_lines {
  112. my ($print, $filename, $lines) = @_;
  113. return output($print, $filename, lines => $lines);
  114. }
  115. sub write_svg {
  116. my ($svg, $filename) = @_;
  117. open my $fh, '>', $filename;
  118. print $fh $svg->xmlify;
  119. close $fh;
  120. printf "SVG written to %s\n", $filename;
  121. }
  122. 1;