aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Somerville <matthew@mysociety.org>2019-11-13 17:28:28 +0000
committerMatthew Somerville <matthew@mysociety.org>2020-01-08 11:36:58 +0000
commit751d2f231353354e7607d9c5e0db2d8945419fbf (patch)
treeb5b2a9de6605d0cf8cfb10b87757d5c9f170fc2f
parentabeb4050e895ff93f5f66affd1ff07c3943bd2a9 (diff)
[Cheshire East] Use own map tiles.
-rw-r--r--perllib/FixMyStreet/Cobrand/CheshireEast.pm2
-rw-r--r--perllib/FixMyStreet/Map/CheshireEast.pm70
-rw-r--r--perllib/FixMyStreet/Map/OSM.pm40
-rw-r--r--t/map/cheshireeast.t18
-rw-r--r--t/map/tests.t1
-rw-r--r--web/cobrands/cheshireeast/assets.js7
-rw-r--r--web/js/map-cheshireeast.js33
7 files changed, 149 insertions, 22 deletions
diff --git a/perllib/FixMyStreet/Cobrand/CheshireEast.pm b/perllib/FixMyStreet/Cobrand/CheshireEast.pm
index a2c6c1c19..de64f0863 100644
--- a/perllib/FixMyStreet/Cobrand/CheshireEast.pm
+++ b/perllib/FixMyStreet/Cobrand/CheshireEast.pm
@@ -46,6 +46,8 @@ sub geocoder_munge_results {
$result->{display_name} =~ s/, Cheshire East, North West England, England//;
}
+sub map_type { 'CheshireEast' }
+
sub default_map_zoom { 3 }
sub on_map_default_status { 'open' }
diff --git a/perllib/FixMyStreet/Map/CheshireEast.pm b/perllib/FixMyStreet/Map/CheshireEast.pm
new file mode 100644
index 000000000..4e59f2593
--- /dev/null
+++ b/perllib/FixMyStreet/Map/CheshireEast.pm
@@ -0,0 +1,70 @@
+package FixMyStreet::Map::CheshireEast;
+use base 'FixMyStreet::Map::OSM';
+
+use strict;
+use Utils;
+
+use constant MIN_ZOOM_LEVEL => 7;
+
+sub map_javascript { [
+ '/vendor/OpenLayers/OpenLayers.wfs.js',
+ '/js/map-OpenLayers.js',
+ '/js/map-cheshireeast.js',
+] }
+
+sub tile_parameters { {
+ origin_x => -3276800,
+ origin_y => 3276800,
+} }
+
+sub resolutions { (
+ 1792.003584007169,
+ 896.0017920035843,
+ 448.0008960017922,
+ 224.0004480008961,
+ 112.000224000448,
+ 56.000112000224014,
+ 28.000056000111993,
+ 14.000028000056004,
+ 7.000014000028002,
+ 2.8000056000112004,
+ 1.4000028000056002,
+ 0.7000014000028001,
+ 0.35000070000140004,
+ 0.14000028000056003,
+) }
+
+my $url = 'https://maps-cache.cheshiresharedservices.gov.uk/maps/?wmts/CE_OS_AllBasemaps_COLOUR/oscce_grid/%d/%d/%d.jpeg&KEY=3a3f5c60eca1404ea114e6941c9d3895';
+
+sub map_tiles {
+ my ( $self, %params ) = @_;
+ my ( $x, $y, $z ) = ( $params{x_tile}, $params{y_tile}, $params{zoom_act} );
+ return [
+ sprintf($url, $z, $x-1, $y-1),
+ sprintf($url, $z, $x, $y-1),
+ sprintf($url, $z, $x-1, $y),
+ sprintf($url, $z, $x, $y),
+ ];
+}
+
+sub latlon_to_tile($$$$) {
+ my ($self, $lat, $lon, $zoom) = @_;
+ my ($x, $y) = eval { Utils::convert_latlon_to_en($lat, $lon) };
+ my $tile_params = $self->tile_parameters;
+ my $res = ($self->resolutions)[$zoom];
+ my $fx = ( $x - $tile_params->{origin_x} ) / ($res * 256);
+ my $fy = ( $tile_params->{origin_y} - $y ) / ($res * 256);
+ return ( $fx, $fy );
+}
+
+sub tile_to_latlon {
+ my ($self, $fx, $fy, $zoom) = @_;
+ my $tile_params = $self->tile_parameters;
+ my $res = ($self->resolutions)[$zoom];
+ my $x = $fx * $res * 256 + $tile_params->{origin_x};
+ my $y = $tile_params->{origin_y} - $fy * $res * 256;
+ my ($lat, $lon) = Utils::convert_en_to_latlon($x, $y);
+ return ( $lat, $lon );
+}
+
+1;
diff --git a/perllib/FixMyStreet/Map/OSM.pm b/perllib/FixMyStreet/Map/OSM.pm
index a6cb6acea..ef465d7dc 100644
--- a/perllib/FixMyStreet/Map/OSM.pm
+++ b/perllib/FixMyStreet/Map/OSM.pm
@@ -87,10 +87,10 @@ sub generate_map_data {
$zoom = $numZoomLevels - 1 if $zoom >= $numZoomLevels;
$zoom = 0 if $zoom < 0;
$params{zoom_act} = $zoomOffset + $zoom;
- ($params{x_tile}, $params{y_tile}) = latlon_to_tile_with_adjust($params{latitude}, $params{longitude}, $params{zoom_act});
+ ($params{x_tile}, $params{y_tile}) = $self->latlon_to_tile_with_adjust($params{latitude}, $params{longitude}, $params{zoom_act});
foreach my $pin (@{$params{pins}}) {
- ($pin->{px}, $pin->{py}) = latlon_to_px($pin->{latitude}, $pin->{longitude}, $params{x_tile}, $params{y_tile}, $params{zoom_act});
+ ($pin->{px}, $pin->{py}) = $self->latlon_to_px($pin->{latitude}, $pin->{longitude}, $params{x_tile}, $params{y_tile}, $params{zoom_act});
}
return {
@@ -102,24 +102,24 @@ sub generate_map_data {
zoom => $zoom,
zoomOffset => $zoomOffset,
numZoomLevels => $numZoomLevels,
- compass => compass( $params{x_tile}, $params{y_tile}, $params{zoom_act} ),
+ compass => $self->compass( $params{x_tile}, $params{y_tile}, $params{zoom_act} ),
};
}
sub compass {
- my ( $x, $y, $z ) = @_;
+ my ( $self, $x, $y, $z ) = @_;
return {
- north => [ map { Utils::truncate_coordinate($_) } tile_to_latlon( $x, $y-1, $z ) ],
- south => [ map { Utils::truncate_coordinate($_) } tile_to_latlon( $x, $y+1, $z ) ],
- west => [ map { Utils::truncate_coordinate($_) } tile_to_latlon( $x-1, $y, $z ) ],
- east => [ map { Utils::truncate_coordinate($_) } tile_to_latlon( $x+1, $y, $z ) ],
- here => [ map { Utils::truncate_coordinate($_) } tile_to_latlon( $x, $y, $z ) ],
+ north => [ map { Utils::truncate_coordinate($_) } $self->tile_to_latlon( $x, $y-1, $z ) ],
+ south => [ map { Utils::truncate_coordinate($_) } $self->tile_to_latlon( $x, $y+1, $z ) ],
+ west => [ map { Utils::truncate_coordinate($_) } $self->tile_to_latlon( $x-1, $y, $z ) ],
+ east => [ map { Utils::truncate_coordinate($_) } $self->tile_to_latlon( $x+1, $y, $z ) ],
+ here => [ map { Utils::truncate_coordinate($_) } $self->tile_to_latlon( $x, $y, $z ) ],
};
}
# Given a lat/lon, convert it to OSM tile co-ordinates (precise).
-sub latlon_to_tile($$$) {
- my ($lat, $lon, $zoom) = @_;
+sub latlon_to_tile($$$$) {
+ my ($self, $lat, $lon, $zoom) = @_;
my $x_tile = ($lon + 180) / 360 * 2**$zoom;
my $y_tile = (1 - log(tan(deg2rad($lat)) + sec(deg2rad($lat))) / pi) / 2 * 2**$zoom;
return ( $x_tile, $y_tile );
@@ -127,9 +127,9 @@ 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) = latlon_to_tile($lat, $lon, $zoom);
+sub latlon_to_tile_with_adjust($$$$) {
+ my ($self, $lat, $lon, $zoom) = @_;
+ my ($x_tile, $y_tile) = $self->latlon_to_tile($lat, $lon, $zoom);
# Try and have point near centre of map
if ($x_tile - int($x_tile) > 0.5) {
@@ -143,7 +143,7 @@ sub latlon_to_tile_with_adjust($$$) {
}
sub tile_to_latlon {
- my ($x, $y, $zoom) = @_;
+ my ($self, $x, $y, $zoom) = @_;
my $n = 2 ** $zoom;
my $lon = $x / $n * 360 - 180;
my $lat = rad2deg(atan(sinh(pi * (1 - 2 * $y / $n))));
@@ -151,9 +151,9 @@ sub tile_to_latlon {
}
# 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);
+sub latlon_to_px($$$$$$) {
+ my ($self, $lat, $lon, $x_tile, $y_tile, $zoom) = @_;
+ my ($pin_x_tile, $pin_y_tile) = $self->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);
@@ -182,8 +182,8 @@ 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 = MIN_ZOOM_LEVEL + (defined $c->get_param('zoom') ? $c->get_param('zoom') : 3);
- my ($lat, $lon) = tile_to_latlon($tile_x, $tile_y, $zoom);
+ my $zoom = $self->MIN_ZOOM_LEVEL + (defined $c->get_param('zoom') ? $c->get_param('zoom') : 3);
+ my ($lat, $lon) = $self->tile_to_latlon($tile_x, $tile_y, $zoom);
return ( $lat, $lon );
}
diff --git a/t/map/cheshireeast.t b/t/map/cheshireeast.t
new file mode 100644
index 000000000..a90a1606e
--- /dev/null
+++ b/t/map/cheshireeast.t
@@ -0,0 +1,18 @@
+use Test::More;
+use FixMyStreet::Map::CheshireEast;
+
+# https://maps-cache.cheshiresharedservices.gov.uk/maps/?wmts/CE_OS_AllBasemaps_COLOUR/oscce_grid/10/10187/8134.jpeg&KEY=3a3f5c60eca1404ea114e6941c9d3895
+my $tiles = FixMyStreet::Map::CheshireEast->map_tiles(x_tile => 10187, y_tile => 8134, zoom_act => 10);
+$tiles = [ map { m{(\d+/\d+/\d+)}; $1; } @$tiles ];
+is_deeply $tiles, [ '10/10186/8133', '10/10187/8133', '10/10186/8134', '10/10187/8134' ];
+
+use Data::Dumper;
+my ($x, $y) = FixMyStreet::Map::CheshireEast->latlon_to_tile_with_adjust(53.150624, -2.386809, 10);
+is $x, 10187;
+is $y, 8134;
+
+my ($lat, $lon) = FixMyStreet::Map::CheshireEast->tile_to_latlon(10187, 8134, 10);
+is sprintf("%.6f", $lat), 53.150624;
+is sprintf("%.6f", $lon), -2.386809;
+
+done_testing();
diff --git a/t/map/tests.t b/t/map/tests.t
index 499447ad5..02ec4e69d 100644
--- a/t/map/tests.t
+++ b/t/map/tests.t
@@ -7,6 +7,7 @@ my $requires = {
'Bromley' => 'map-fms.js',
'Buckinghamshire' => 'map-wmts-buckinghamshire.js',
'Lincolnshire' => 'lincolnshire/assets.js',
+ 'CheshireEast' => 'map-cheshireeast.js',
'FMS' => 'map-fms.js',
'Google' => 'map-google.js',
'GoogleOL' => 'map-google-ol.js',
diff --git a/web/cobrands/cheshireeast/assets.js b/web/cobrands/cheshireeast/assets.js
index 1b1c254e3..720b02936 100644
--- a/web/cobrands/cheshireeast/assets.js
+++ b/web/cobrands/cheshireeast/assets.js
@@ -6,8 +6,11 @@ if (!fixmystreet.maps) {
var defaults = {
wfs_url: "https://tilma.mysociety.org/mapserver/cheshireeast",
- max_resolution: 4.777314267158508,
- min_resolution: 0.5971642833948135,
+ max_resolution: {
+ fixmystreet: 4.777314267158508,
+ cheshireeast: 1.4000028000056002
+ },
+ min_resolution: 0.00001,
attributes: {
central_asset_id: 'central_as',
site_code: 'site_code'
diff --git a/web/js/map-cheshireeast.js b/web/js/map-cheshireeast.js
new file mode 100644
index 000000000..cedc92dba
--- /dev/null
+++ b/web/js/map-cheshireeast.js
@@ -0,0 +1,33 @@
+fixmystreet.maps.config = function() {
+ fixmystreet.controls = [
+ new OpenLayers.Control.Attribution(),
+ new OpenLayers.Control.ArgParserFMS(),
+ new OpenLayers.Control.Navigation(),
+ new OpenLayers.Control.PermalinkFMS('map'),
+ new OpenLayers.Control.PanZoomFMS({id: 'fms_pan_zoom' })
+ ];
+ /* Linking back to around from report page, keeping track of map moves */
+ if ( fixmystreet.page == 'report' ) {
+ fixmystreet.controls.push( new OpenLayers.Control.PermalinkFMS('key-tool-problems-nearby', '/around') );
+ }
+ fixmystreet.map_type = OpenLayers.Layer.CheshireEast;
+};
+
+OpenLayers.Layer.CheshireEast = OpenLayers.Class(OpenLayers.Layer.XYZ, {
+ url: 'https://maps-cache.cheshiresharedservices.gov.uk/maps/?wmts/CE_OS_AllBasemaps_COLOUR/oscce_grid/${z}/${x}/${y}.jpeg&KEY=3a3f5c60eca1404ea114e6941c9d3895',
+
+ initialize: function(name, options) {
+ options = OpenLayers.Util.extend({
+ units: "m",
+ projection: new OpenLayers.Projection("EPSG:27700"),
+ maxExtent: new OpenLayers.Bounds(-3276800, -3276800, 3276800, 3276800),
+ resolutions: [1792.003584007169, 896.0017920035843, 448.0008960017922, 224.0004480008961, 112.000224000448, 56.000112000224014, 28.000056000111993, 14.000028000056004, 7.000014000028002, 2.8000056000112004, 1.4000028000056002, 0.7000014000028001, 0.35000070000140004, 0.14000028000056003].slice(fixmystreet.zoomOffset || 0),
+ }, options);
+ OpenLayers.Layer.XYZ.prototype.initialize.call(this, name, this.url, options);
+ },
+
+ CLASS_NAME: "OpenLayers.Layer.CheshireEast"
+});
+
+fixmystreet.maps.zoom_for_normal_size = 7;
+fixmystreet.maps.zoom_for_small_size = 4;