aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/Map
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet/Map')
-rw-r--r--perllib/FixMyStreet/Map/Google.pm35
-rw-r--r--perllib/FixMyStreet/Map/GoogleOL.pm22
-rw-r--r--perllib/FixMyStreet/Map/OSM.pm31
-rw-r--r--perllib/FixMyStreet/Map/OSM/MapQuest.pm6
-rw-r--r--perllib/FixMyStreet/Map/Zurich.pm169
5 files changed, 234 insertions, 29 deletions
diff --git a/perllib/FixMyStreet/Map/Google.pm b/perllib/FixMyStreet/Map/Google.pm
index c0d83e35a..9deefc033 100644
--- a/perllib/FixMyStreet/Map/Google.pm
+++ b/perllib/FixMyStreet/Map/Google.pm
@@ -3,12 +3,17 @@
# FixMyStreet:Map::Google
# Google maps on FixMyStreet.
#
-# Copyright (c) 2010 UK Citizens Online Democracy. All rights reserved.
+# Copyright (c) 2013 UK Citizens Online Democracy. All rights reserved.
# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
package FixMyStreet::Map::Google;
use strict;
+use mySociety::Gaze;
+use Utils;
+
+use constant ZOOM_LEVELS => 6;
+use constant MIN_ZOOM_LEVEL => 13;
# display_map C PARAMS
# PARAMS include:
@@ -17,9 +22,37 @@ use strict;
# PINS is array of pins to show, location and colour
sub display_map {
my ($self, $c, %params) = @_;
+
+ my $numZoomLevels = ZOOM_LEVELS;
+ my $zoomOffset = MIN_ZOOM_LEVEL;
+ if ($params{any_zoom}) {
+ $numZoomLevels = 19;
+ $zoomOffset = 0;
+ }
+
+ # Adjust zoom level dependent upon population density
+ my $dist = $c->stash->{distance}
+ || mySociety::Gaze::get_radius_containing_population( $params{latitude}, $params{longitude}, 200_000 );
+ my $default_zoom = $c->cobrand->default_map_zoom() ? $c->cobrand->default_map_zoom() : $numZoomLevels - 4;
+ $default_zoom = $numZoomLevels - 3 if $dist < 10;
+
+ # Map centre may be overridden in the query string
+ $params{latitude} = Utils::truncate_coordinate($c->req->params->{lat} + 0)
+ if defined $c->req->params->{lat};
+ $params{longitude} = Utils::truncate_coordinate($c->req->params->{lon} + 0)
+ if defined $c->req->params->{lon};
+
+ my $zoom = defined $c->req->params->{zoom} ? $c->req->params->{zoom} + 0 : $default_zoom;
+ $zoom = $numZoomLevels - 1 if $zoom >= $numZoomLevels;
+ $zoom = 0 if $zoom < 0;
+ $params{zoom_act} = $zoomOffset + $zoom;
+
$c->stash->{map} = {
%params,
type => 'google',
+ zoom => $zoom,
+ zoomOffset => $zoomOffset,
+ numZoomLevels => $numZoomLevels,
};
}
diff --git a/perllib/FixMyStreet/Map/GoogleOL.pm b/perllib/FixMyStreet/Map/GoogleOL.pm
new file mode 100644
index 000000000..64baf8d36
--- /dev/null
+++ b/perllib/FixMyStreet/Map/GoogleOL.pm
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+#
+# FixMyStreet:Map::GoogleOL
+# Google maps on FixMyStreet, using OpenLayers.
+#
+# Copyright (c) 2013 UK Citizens Online Democracy. All rights reserved.
+# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/
+
+package FixMyStreet::Map::GoogleOL;
+use parent 'FixMyStreet::Map::OSM';
+
+use strict;
+
+sub map_type {
+ return '""';
+}
+
+sub map_template {
+ return 'google-ol';
+}
+
+1;
diff --git a/perllib/FixMyStreet/Map/OSM.pm b/perllib/FixMyStreet/Map/OSM.pm
index 6b3bebba2..74af0e9f3 100644
--- a/perllib/FixMyStreet/Map/OSM.pm
+++ b/perllib/FixMyStreet/Map/OSM.pm
@@ -13,7 +13,7 @@ use Math::Trig;
use mySociety::Gaze;
use Utils;
-use constant ZOOM_LEVELS => 5;
+use constant ZOOM_LEVELS => 6;
use constant MIN_ZOOM_LEVEL => 13;
sub map_type {
@@ -55,15 +55,15 @@ sub display_map {
my $numZoomLevels = ZOOM_LEVELS;
my $zoomOffset = MIN_ZOOM_LEVEL;
if ($params{any_zoom}) {
- $numZoomLevels = 18;
+ $numZoomLevels = 19;
$zoomOffset = 0;
}
# Adjust zoom level dependent upon population density
my $dist = $c->stash->{distance}
|| mySociety::Gaze::get_radius_containing_population( $params{latitude}, $params{longitude}, 200_000 );
- my $default_zoom = $c->cobrand->default_map_zoom() ? $c->cobrand->default_map_zoom() : $numZoomLevels - 3;
- $default_zoom = $numZoomLevels - 2 if $dist < 10;
+ my $default_zoom = $c->cobrand->default_map_zoom() ? $c->cobrand->default_map_zoom() : $numZoomLevels - 4;
+ $default_zoom = $numZoomLevels - 3 if $dist < 10;
# Map centre may be overridden in the query string
$params{latitude} = Utils::truncate_coordinate($c->req->params->{lat} + 0)
@@ -94,29 +94,6 @@ sub display_map {
};
}
-sub map_pins {
- my ($self, $c, $interval) = @_;
-
- my $bbox = $c->req->param('bbox');
- my ( $min_lon, $min_lat, $max_lon, $max_lat ) = split /,/, $bbox;
-
- my ( $around_map, $around_map_list, $nearby, $dist ) =
- FixMyStreet::Map::map_features_bounds( $c, $min_lon, $min_lat, $max_lon, $max_lat, $interval );
-
- # create a list of all the pins
- my @pins = map {
- # Here we might have a DB::Problem or a DB::Nearby, we always want the problem.
- my $p = (ref $_ eq 'FixMyStreet::App::Model::DB::Nearby') ? $_->problem : $_;
- my $colour = $c->cobrand->pin_colour( $p, 'around' );
- [ $p->latitude, $p->longitude,
- $colour,
- $p->id, $p->title
- ]
- } @$around_map, @$nearby;
-
- return (\@pins, $around_map_list, $nearby, $dist);
-}
-
sub compass {
my ( $x, $y, $z ) = @_;
return {
diff --git a/perllib/FixMyStreet/Map/OSM/MapQuest.pm b/perllib/FixMyStreet/Map/OSM/MapQuest.pm
index 4751679f5..a7f1b334e 100644
--- a/perllib/FixMyStreet/Map/OSM/MapQuest.pm
+++ b/perllib/FixMyStreet/Map/OSM/MapQuest.pm
@@ -15,6 +15,10 @@ sub map_type {
return 'OpenLayers.Layer.OSM.MapQuestOpen';
}
+sub map_template {
+ return 'mapquest-attribution';
+}
+
sub map_tiles {
my ( $self, %params ) = @_;
my ( $x, $y, $z ) = ( $params{x_tile}, $params{y_tile}, $params{zoom_act} );
@@ -28,7 +32,7 @@ sub map_tiles {
}
sub base_tile_url {
- return 'mqcdn.com/tiles/1.0.0/osm/';
+ return 'mqcdn.com/tiles/1.0.0/map/';
}
1;
diff --git a/perllib/FixMyStreet/Map/Zurich.pm b/perllib/FixMyStreet/Map/Zurich.pm
new file mode 100644
index 000000000..e09f8c90f
--- /dev/null
+++ b/perllib/FixMyStreet/Map/Zurich.pm
@@ -0,0 +1,169 @@
+#!/usr/bin/perl
+#
+# FixMyStreet:Map::Zurich
+# Zurich have their own tileserver.
+#
+# Copyright (c) 2012 UK Citizens Online Democracy. All rights reserved.
+# Email: steve@mysociety.org; WWW: http://www.mysociety.org/
+
+package FixMyStreet::Map::Zurich;
+
+use strict;
+use Geo::Coordinates::CH1903;
+use Math::Trig;
+use Utils;
+
+use constant ZOOM_LEVELS => 8;
+use constant DEFAULT_ZOOM => 5;
+use constant MIN_ZOOM_LEVEL => 0;
+use constant ID_OFFSET => 2;
+
+sub map_tiles {
+ my ( $self, %params ) = @_;
+ my ( $col, $row, $z ) = ( $params{x_tile}, $params{y_tile}, $params{matrix_id} );
+ my $tile_url = $self->base_tile_url();
+ 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",
+ ];
+}
+
+sub base_tile_url {
+ return '/maps/Hybrid/1.0.0/Hybrid/default/nativeTileMatrixSet';
+}
+
+sub copyright {
+ return '&copy; Stadt Z&uuml;rich';
+}
+
+# display_map C PARAMS
+# PARAMS include:
+# latitude, longitude for the centre point of the map
+# CLICKABLE is set if the map is clickable
+# PINS is array of pins to show, location and colour
+sub display_map {
+ my ($self, $c, %params) = @_;
+
+ # Map centre may be overridden in the query string
+ $params{latitude} = Utils::truncate_coordinate($c->req->params->{lat} + 0)
+ if defined $c->req->params->{lat};
+ $params{longitude} = Utils::truncate_coordinate($c->req->params->{lon} + 0)
+ if defined $c->req->params->{lon};
+
+ my $zoom = defined $c->req->params->{zoom}
+ ? $c->req->params->{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{x_tile}, $params{y_tile}, $params{matrix_id}) = latlon_to_tile_with_adjust($params{latitude}, $params{longitude}, $zoom);
+
+ foreach my $pin (@{$params{pins}}) {
+ ($pin->{px}, $pin->{py}) = latlon_to_px($pin->{latitude}, $pin->{longitude}, $params{x_tile}, $params{y_tile}, $zoom);
+ }
+
+ $c->stash->{map} = {
+ %params,
+ type => 'zurich',
+ map_type => 'OpenLayers.Layer.WMTS',
+ tiles => $self->map_tiles( %params ),
+ copyright => $self->copyright(),
+ zoom => $zoom,
+ zoomOffset => MIN_ZOOM_LEVEL,
+ numZoomLevels => ZOOM_LEVELS,
+ };
+}
+
+# Given a lat/lon, convert it to Zurch tile co-ordinates (precise).
+sub latlon_to_tile($$$) {
+ my ($lat, $lon, $zoom) = @_;
+
+ 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' );
+ my $tileOrigin = { lat => 30814423, lon => -29386322 };
+ my $tileSize = 256;
+ my $res = $scales[$matrix_id] / (39.3701 * 96); # OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH
+
+ my $fx = ( $x - $tileOrigin->{lon} ) / ($res * $tileSize);
+ my $fy = ( $tileOrigin->{lat} - $y ) / ($res * $tileSize);
+
+ return ( $fx, $fy, $matrix_id );
+}
+
+# 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);
+
+ # Try and have point near centre of map
+ if ($x_tile - int($x_tile) > 0.5) {
+ $x_tile += 1;
+ }
+ if ($y_tile - int($y_tile) > 0.5) {
+ $y_tile += 1;
+ }
+
+ return ( int($x_tile), int($y_tile), $matrix_id );
+}
+
+sub tile_to_latlon {
+ my ($fx, $fy, $zoom) = @_;
+
+ my $matrix_id = $zoom + ID_OFFSET;
+ my @scales = ( '250000', '125000', '64000', '32000', '16000', '8000', '4000', '2000', '1000', '500' );
+ my $tileOrigin = { lat => 30814423, lon => -29386322 };
+ my $tileSize = 256;
+ my $res = $scales[$matrix_id] / (39.3701 * 96); # OpenLayers.INCHES_PER_UNIT[units] * OpenLayers.DOTS_PER_INCH
+
+ my $x = $fx * $res * $tileSize + $tileOrigin->{lon};
+ my $y = $tileOrigin->{lat} - $fy * $res * $tileSize;
+
+ my ($lat, $lon) = Geo::Coordinates::CH1903::to_latlon($x, $y);
+
+ return ( $lat, $lon );
+}
+
+# Given a lat/lon, convert it to pixel co-ordinates from the top left of the map
+sub latlon_to_px($$$$$) {
+ my ($lat, $lon, $x_tile, $y_tile, $zoom) = @_;
+ my ($pin_x_tile, $pin_y_tile) = latlon_to_tile($lat, $lon, $zoom);
+ my $pin_x = tile_to_px($pin_x_tile, $x_tile);
+ my $pin_y = tile_to_px($pin_y_tile, $y_tile);
+ return ($pin_x, $pin_y);
+}
+
+# Convert tile co-ordinates to pixel co-ordinates from top left of map
+# C is centre tile reference of displayed map
+sub tile_to_px {
+ my ($p, $c) = @_;
+ $p = 256 * ($p - $c + 1);
+ $p = int($p + .5 * ($p <=> 0));
+ return $p;
+}
+
+sub click_to_tile {
+ my ($pin_tile, $pin) = @_;
+ $pin -= 256 while $pin > 256;
+ $pin += 256 while $pin < 0;
+ return $pin_tile + $pin / 256;
+}
+
+# Given some click co-ords (the tile they were on, and where in the
+# tile they were), convert to WGS84 and return.
+sub click_to_wgs84 {
+ my ($self, $c, $pin_tile_x, $pin_x, $pin_tile_y, $pin_y) = @_;
+ my $tile_x = click_to_tile($pin_tile_x, $pin_x);
+ my $tile_y = click_to_tile($pin_tile_y, $pin_y);
+ my $zoom = (defined $c->req->params->{zoom} ? $c->req->params->{zoom} : DEFAULT_ZOOM);
+ my ($lat, $lon) = tile_to_latlon($tile_x, $tile_y, $zoom);
+ return ( $lat, $lon );
+}
+
+1;