diff options
author | Zarino Zappia <mail@zarino.co.uk> | 2015-03-25 16:31:55 +0000 |
---|---|---|
committer | Dave Arter <davea@mysociety.org> | 2015-10-06 09:09:25 +0100 |
commit | 319b49f0206fda26d7cf0fdc71eed6c4195594ae (patch) | |
tree | 79d2d7c3fe1359e4c323b9f5fe20d2b8c2d4c61b /perllib | |
parent | da3229b5508c7f037eec594648e9062b2a872ec9 (diff) |
[Zurich] Add maps to Zurich admin report print view
- Includes a small map at the top of the first page and a second
full-width map on a separate page.
- upgrades tiles to the new 512px ones already used by JS
as implemented in https://github.com/mysociety/FixMyStreet-Commercial/issues/668
- Uses jQuery to clone a copy of the "noscript" map elsewhere into
the DOM, because the original is too far from where we need it.
- extracts maps/openlayers.html to call maps/noscript_map.html
- specialises the Zurich version to allow a richer structure to be
returned, including arbitrary sized map
- Map::Zurich now returns nearly arbitrary sized map tiles
- second larger map is prepared (only for admin/report_edit)
See mysociety/FixMyStreet-Commercial#677
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/Map/Zurich.pm | 155 |
2 files changed, 125 insertions, 31 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 677aa66d7..ae64bd42d 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -678,6 +678,7 @@ sub report_edit : Path('report_edit') : Args(1) { type => 'big', } ] : [], + print_report => 1, ); } diff --git a/perllib/FixMyStreet/Map/Zurich.pm b/perllib/FixMyStreet/Map/Zurich.pm index 04fd596d1..3e198f820 100644 --- a/perllib/FixMyStreet/Map/Zurich.pm +++ b/perllib/FixMyStreet/Map/Zurich.pm @@ -15,22 +15,49 @@ use constant ZOOM_LEVELS => 9; use constant DEFAULT_ZOOM => 5; use constant MIN_ZOOM_LEVEL => 0; use constant ID_OFFSET => 2; -use constant TILE_SIZE => 256; +use constant TILE_SIZE => 512; sub map_tiles { - my ( $self, %params ) = @_; - my ( $col, $row, $z ) = ( $params{x_tile}, $params{y_tile}, $params{matrix_id} ); + my ($self, %params) = @_; + my ($left_col, $top_row, $z) = @params{'x_left_tile', 'y_top_tile', 'matrix_id'}; my $tile_url = $self->base_tile_url(); + my $cols = $params{cols}; + my $rows = $params{rows}; + + my @col_offsets = (0.. ($cols-1) ); + my @row_offsets = (0.. ($rows-1) ); + return [ - "$tile_url/$z/" . ($row - 1) . "/" . ($col - 1) . ".jpg", - "$tile_url/$z/" . ($row - 1) . "/$col.jpg", - "$tile_url/$z/$row/" . ($col - 1) . ".jpg", - "$tile_url/$z/$row/$col.jpg", + map { + my $row_offset = $_; + [ + map { + my $col_offset = $_; + my $row = $top_row + $row_offset; + my $col = $left_col + $col_offset; + my $src = sprintf '%s/%d/%d/%d.jpg', + $tile_url, $z, $row, $col; + my $dotted_id = sprintf '%d.%d', $col, $row; + + # return the data structure for the cell + +{ + src => $src, + row_offset => $row_offset, + col_offset => $col_offset, + dotted_id => $dotted_id, + alt => "Map tile $dotted_id", # TODO "NW map tile"? + } + } + @col_offsets + ] + } + @row_offsets ]; } sub base_tile_url { - return '/maps/Hybrid/1.0.0/Hybrid/default/nativeTileMatrixSet'; + # use the new 512px maps as used by Javascript + return 'http://www.gis.stadt-zuerich.ch/maps/rest/services/tiled/LuftbildHybrid/MapServer/WMTS/tile/1.0.0/tiled_LuftbildHybrid/default/default028mm'; } sub copyright { @@ -51,29 +78,77 @@ sub display_map { $params{longitude} = Utils::truncate_coordinate($c->get_param('lon') + 0) if defined $c->get_param('lon'); - my $zoom = defined $c->get_param('zoom') - ? $c->get_param('zoom') + 0 - : $c->stash->{page} eq 'report' - ? DEFAULT_ZOOM+1 - : DEFAULT_ZOOM; - $zoom = ZOOM_LEVELS - 1 if $zoom >= ZOOM_LEVELS; - $zoom = 0 if $zoom < 0; + $params{rows} //= 2; # 2x2 square is default + $params{cols} //= 2; + + $params{zoom} = do { + my $zoom = defined $c->get_param('zoom') + ? $c->get_param('zoom') + 0 + : $c->stash->{page} eq 'report' + ? DEFAULT_ZOOM+1 + : DEFAULT_ZOOM; + $zoom = ZOOM_LEVELS - 1 if $zoom >= ZOOM_LEVELS; + $zoom = 0 if $zoom < 0; + $zoom; + }; - ($params{x_tile}, $params{y_tile}, $params{matrix_id}) = latlon_to_tile_with_adjust($params{latitude}, $params{longitude}, $zoom); + $c->stash->{map} = $self->get_map_hash( %params ); - foreach my $pin (@{$params{pins}}) { - ($pin->{px}, $pin->{py}) = latlon_to_px($pin->{latitude}, $pin->{longitude}, $params{x_tile}, $params{y_tile}, $zoom); + if ($params{print_report}) { + $params{zoom}++ unless $params{zoom} >= ZOOM_LEVELS; + $c->stash->{print_report_map} + = $self->get_map_hash( + %params, + img_type => 'img', + cols => 4, rows => 4, + ); + # NB: we can passthrough img_type as literal here, as only designed for print + + # NB we can do arbitrary size, including non-squares, however we'd have + # to modify .square-map style with padding-bottom percentage calculated in + # an inline style: + # <zarino> in which case, the only change that'd be required is + # removing { padding-bottom: 100% } from .square-map__outer, putting + # the percentage into an inline style on the element itself, and then + # probably renaming .square-map__* to .fixed-aspect-map__* or something + # since it's no longer necessarily square } +} + +sub get_map_hash { + my ($self, %params) = @_; + + @params{'x_centre_tile', 'y_centre_tile', 'matrix_id'} + = latlon_to_tile_with_adjust( + @params{'latitude', 'longitude', 'zoom', 'rows', 'cols'}); - $c->stash->{map} = { + # centre_(row|col) is either in middle, or just to right. + # e.g. if centre is the number in parens: + # 1 (2) 3 => 2 - int( 3/2 ) = 1 + # 1 2 (3) 4 => 3 - int( 4/2 ) = 1 + $params{x_left_tile} = $params{x_centre_tile} - int($params{cols} / 2); + $params{y_top_tile} = $params{y_centre_tile} - int($params{rows} / 2); + + $params{pins} = [ + map { + my $pin = { %$_ }; # shallow clone + ($pin->{px}, $pin->{py}) + = latlon_to_px($pin->{latitude}, $pin->{longitude}, + @params{'x_left_tile', 'y_top_tile', 'zoom'}); + $pin; + } @{ $params{pins} } + ]; + + return { %params, type => 'zurich', map_type => 'OpenLayers.Layer.WMTS', tiles => $self->map_tiles( %params ), copyright => $self->copyright(), - zoom => $zoom, + zoom => $params{zoom},, zoomOffset => MIN_ZOOM_LEVEL, numZoomLevels => ZOOM_LEVELS, + tile_size => TILE_SIZE, }; } @@ -84,9 +159,17 @@ sub latlon_to_tile($$$) { my ($x, $y) = Geo::Coordinates::CH1903::from_latlon($lat, $lon); my $matrix_id = $zoom + ID_OFFSET; - my @scales = ( '250000', '125000', '64000', '32000', '16000', '8000', '4000', '2000', '1000', '500', '250' ); + my @scales = ( + '250000', '125000', + '64000', '32000', + '16000', '8000', + '4000', '2000', + '1000', '500', + '250' + ); my $tileOrigin = { lat => 30814423, lon => -29386322 }; - my $res = $scales[$matrix_id] / (39.3701 * 96); # OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH + my $res = $scales[$matrix_id] / (39.3701 * 96); + # OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH my $fx = ( $x - $tileOrigin->{lon} ) / ($res * TILE_SIZE); my $fy = ( $tileOrigin->{lat} - $y ) / ($res * TILE_SIZE); @@ -96,16 +179,26 @@ sub latlon_to_tile($$$) { # Given a lat/lon, convert it to OSM tile co-ordinates (nearest actual tile, # adjusted so the point will be near the centre of a 2x2 tiled map). -sub latlon_to_tile_with_adjust($$$) { - my ($lat, $lon, $zoom) = @_; - my ($x_tile, $y_tile, $matrix_id) = latlon_to_tile($lat, $lon, $zoom); +# +# Takes parameter for rows/cols. For even sizes (2x2, 4x4 etc.) will +# do adjustment, but simply returns actual for odd sizes. +# +sub latlon_to_tile_with_adjust { + my ($lat, $lon, $zoom, $rows, $cols) = @_; + my ($x_tile, $y_tile, $matrix_id) + = my @ret + = latlon_to_tile($lat, $lon, $zoom); - # Try and have point near centre of map - if ($x_tile - int($x_tile) > 0.5) { - $x_tile += 1; + # Try and have point near centre of map, passing through if odd + unless ($cols % 2) { + if ($x_tile - int($x_tile) > 0.5) { + $x_tile += 1; + } } - if ($y_tile - int($y_tile) > 0.5) { - $y_tile += 1; + unless ($rows % 2) { + if ($y_tile - int($y_tile) > 0.5) { + $y_tile += 1; + } } return ( int($x_tile), int($y_tile), $matrix_id ); @@ -140,7 +233,7 @@ sub latlon_to_px($$$$$) { # C is centre tile reference of displayed map sub tile_to_px { my ($p, $c) = @_; - $p = TILE_SIZE * ($p - $c + 1); + $p = TILE_SIZE * ($p - $c); $p = int($p + .5 * ($p <=> 0)); return $p; } |