File Coverage

blib/lib/Geo/OSM/Render/Renderer/SVG.pm
Criterion Covered Total %
statement 62 62 100.0
branch 7 12 58.3
condition 4 8 50.0
subroutine 11 11 100.0
pod 5 5 100.0
total 89 98 90.8


line stmt bran cond sub pod time code
1             # Encoding and name #_{
2              
3             =encoding utf8
4             =head1 NAME
5              
6             Geo::OSM::Render::Renderer::SVG - Specialization of base class L for rendering SVG.
7              
8             =cut
9             package Geo::OSM::Render::Renderer::SVG;
10             #_}
11             #_{ use …
12 2     2   79576 use warnings;
  2         5  
  2         71  
13 2     2   12 use strict;
  2         4  
  2         47  
14              
15 2     2   501 use utf8;
  2         19  
  2         9  
16 2     2   51 use Carp;
  2         4  
  2         117  
17              
18 2     2   947 use SVG;
  2         32465  
  2         16  
19 2     2   3997 use Geo::OSM::Render::Renderer;
  2         6  
  2         1357  
20              
21             #_}
22             our $VERSION = 0.01;
23             our @ISA = qw(Geo::OSM::Render::Renderer);
24             #_{ Synopsis
25              
26             =head1 SYNOPSIS
27              
28              
29             =cut
30             #_}
31             #_{ Overview
32              
33             =head1 OVERVIEW
34              
35            
36              
37             =cut
38              
39             #_}
40             #_{ Methods
41             #_{ POD
42             =head1 METHODS
43             =cut
44             #_}
45             sub new { #_{
46             #_{ POD
47              
48             =head2 new
49              
50             my $proj = Geo::OSM::Render::Projection::CH_LV03->new();
51             my $vp = Geo::OSM::Render::Viewport::Clipped->new(…);
52              
53             my $osm_renderer_svg = Geo::OSM::Render::Renderer->new(
54             $svg_filename,
55             $proj,
56             $vp
57             );
58              
59            
60              
61             $osm_renderer_svg->end();
62              
63             =cut
64              
65             #_}
66              
67 1     1 1 16 my $class = shift;
68 1         3 my $svg_filename = shift;
69              
70 1         12 my $self = $class->SUPER::new(@_);
71              
72 1 50       6 croak "Wrong class $class" unless $self->isa('Geo::OSM::Render::Renderer');
73              
74              
75             # while (@_) {
76             # if ($_[0] -> isa('Geo::OSM::Render::Viewport::Clipped')) {
77             # $self->{viewport} = shift;
78             # next;
79             # }
80             # if ($_[0] -> isa('Geo::OSM::Render::Projection')) {
81             # $self->{projection} = shift;
82             # next;
83             # }
84             # last;
85             # }
86              
87 1 50       7 croak 'Viewport must be Geo::OSM::Render::Viewport::Clipped' unless $self->{viewport } -> isa('Geo::OSM::Render::Viewport::Clipped');
88 1 50       7 croak 'Projection not defined' unless $self->{projection};
89              
90 1 50       94 open ($self->{svg_fh}, '>', $svg_filename) or croak "Could not open $svg_filename";
91              
92             $self->{svg} = SVG->new(
93             width => $self->{viewport}->map_width (),
94             height => $self->{viewport}->map_height()
95 1 50       8 ) or croak "Could not start svg";
96              
97 1         432 return $self;
98              
99             } #_}
100             sub end { #_{
101             #_{ POD
102              
103             =head2 end
104              
105             When finished rendering, this method writes the SVG.
106              
107             =cut
108             #_}
109 1     1 1 56 my $self = shift;
110 1         4 my $svg_text = $self->{svg}->xmlify();
111 1         1036 print {$self->{svg_fh}} $svg_text;
  1         16  
112 1         125 close $self->{svg_fh};
113              
114             } #_}
115             sub render_node { #_{
116             #_{ POD
117              
118             =head2 render_node
119              
120             $osm_renderer_svg -> render_node(
121             $node,
122             r => $radius,
123             styles=> { … }
124             );
125              
126             Renders a L<< node|Geo::OSM::Primitive::Node >>.
127              
128             See also L.
129              
130             =cut
131             #_}
132              
133 2     2 1 69 my $self = shift;
134 2         4 my $node = shift;
135              
136 2         7 my %opts = @_;
137              
138 2         10 $self->SUPER::render_node($node);
139              
140 2   50     6 my $r = delete $opts{radius} // 1;
141 2   50     5 my $styles = delete $opts{styles} // {};
142              
143 2         11 my ($x_map, $y_map) = $self->node_to_map_coordinates($node);
144              
145             $self->{svg}->circle(
146 2         14 cx => $x_map,
147             cy => $y_map,
148             r => $r,
149             style=>$styles
150             );
151              
152             } #_}
153             sub render_way { #_{
154             #_{ POD
155              
156             =head2 render_way
157              
158             $osm_renderer_svg -> render_way(
159             styles=> { … }
160             );
161              
162             Renders a L<< way|Geo::OSM::Primitive::Way >>.
163              
164             See also L<< Geo::OSM::Render::Renderer/render_way >>.
165              
166             =cut
167             #_}
168              
169 1     1 1 52 my $self = shift;
170 1         3 my $way = shift;
171              
172 1         3 my %opts = @_;
173              
174 1   50     5 my $styles = delete $opts{styles} // {};
175              
176 1         5 $self->SUPER::render_way($way);
177              
178 1         5 my @nodes = $way->nodes();
179 1         9 my $points = '';
180 1         2 for my $node (@nodes) {
181 4         9 my ($x_map, $y_map) = $self->node_to_map_coordinates($node);
182 4 100       11 $points .= ' ' if $points;
183 4         22 $points .= "$x_map,$y_map";
184             }
185              
186             $self->{svg}->polyline(
187 1         33 points => $points,
188             style => $styles
189             );
190              
191             } #_}
192             sub line {
193             #_{ POD
194              
195             =head2 line
196              
197             $osm_renderer_svg -> line(
198             $lat_start, $lon_start,
199             $lat_end , $lon_end,
200             styles=> { … }
201             );
202              
203             Draws a line on the SVG map.
204              
205              
206             See also L<< Geo::OSM::Render::Renderer/render_way >>.
207              
208             =cut
209              
210 1     1 1 64 my $self = shift;
211 1         2 my $lat_start = shift;
212 1         2 my $lon_start = shift;
213 1         2 my $lat_end = shift;
214 1         5 my $lon_end = shift;
215 1         3 my %opts = @_;
216              
217 1   50     4 my $styles = delete $opts{styles} // {};
218              
219 1         4 my ($map_x_start, $map_y_start) = $self->lat_lon_to_map_coordinates($lat_start, $lon_start);
220 1         3 my ($map_x_end , $map_y_end ) = $self->lat_lon_to_map_coordinates($lat_end , $lon_end );
221              
222             $self->{svg}->line(
223 1         7 x1 => $map_x_start, y1 => $map_y_start,
224             x2 => $map_x_end , y2 => $map_y_end,
225             style => $styles
226             );
227              
228              
229              
230             #_}
231             }
232             # sub _determine_width_height { #_{
233             # #_{ POD
234             #
235             # =head2 _determine_width_height
236             #
237             # This method determines the width and height of the produced SVG so that C<< max($width, $height) >> is equal to C<< $max_width_height >> which was passed in the
238             # L method.
239             #
240             # =cut
241             #
242             # my $self = shift;
243             #
244             # #_}
245             #
246             # (
247             # $self->{x_min}, $self->{y_min},
248             # $self->{x_max}, $self->{y_max}
249             # ) = (
250             # &{$self->{cp_lat_lon_2_x_y}}($self->{lat_min}, $self->{lon_min}),
251             # &{$self->{cp_lat_lon_2_x_y}}($self->{lat_max}, $self->{lon_max})
252             # );
253             #
254             # my $width_ = $self->{x_max}-$self->{x_min};
255             # my $height_ = $self->{y_max}-$self->{y_min};
256             #
257             # if ($width_ > $height_) {
258             # $self->{width } = $self->{max_width_height};
259             # $self->{height} = $self->{max_width_height} / $width_*$height_;
260             # }
261             # else {
262             # $self->{height} = $self->{max_width_height};
263             # $self->{width } = $self->{max_width_height} / $height_*$width_;
264             # }
265             #
266             # } #_}
267             # sub _x_y_to_svg_x_y { #_{
268             # #_{ POD
269             #
270             # =head2 _x_y_to_svg_x_y
271             #
272             # my ($svg_x, $svg_y) = $self->_x_y_to_svg_x_y($x, $y);
273             #
274             # This method converts an C coordinate pair to svg coordinates. Ideally, the
275             # returned values are greater or equal 0 and smaller or equal to the svg width or
276             # height respectively.
277             #
278             # =cut
279             # #_}
280             #
281             # my $self = shift;
282             # my $x = shift;
283             # my $y = shift;
284             #
285             # my $todo_width = 1;
286             # my $todo_height = 1;
287             #
288             # # In SVG, the coordinate 0/0 marks the *upper* left corner, so
289             # # for y, we have to make an additional substraction for $y.
290             # my $x_ = ($x - $self->{x_min}) / $todo_width * $self->{width };
291             # my $y_ = $self->{height} - ($y - $self->{y_min}) / $todo_height * $self->{height};
292             #
293             # return ($x_, $y_);
294             #
295             # } #_}
296             #_}
297             #_{ POD: Author
298              
299             =head1 AUTHOR
300              
301             René Nyffenegger
302              
303             =cut
304              
305             #_}
306             #_{ POD: Copyright and License
307              
308             =head1 COPYRIGHT AND LICENSE
309             Copyright © 2017 René Nyffenegger, Switzerland. All rights reserved.
310              
311             This program is free software; you can redistribute it and/or modify it
312             under the terms of the the Artistic License (2.0). You may obtain a
313             copy of the full license at: L
314             =cut
315              
316             #_}
317             #_{ POD: Source Code
318              
319             =head1 Source Code
320              
321             The source code is on L<< github|https://github.com/ReneNyffenegger/perl-Geo-OSM-Render >>. Meaningful pull requests are welcome.
322              
323             =cut
324              
325             #_}
326              
327             'tq84';