aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/Alert.pm14
-rw-r--r--perllib/FixMyStreet/Geocode.pm36
-rw-r--r--perllib/FixMyStreet/Map.pm92
-rw-r--r--perllib/FixMyStreet/Map/Tilma/Original.pm56
4 files changed, 131 insertions, 67 deletions
diff --git a/perllib/FixMyStreet/Alert.pm b/perllib/FixMyStreet/Alert.pm
index 9996f03c8..59683be0c 100644
--- a/perllib/FixMyStreet/Alert.pm
+++ b/perllib/FixMyStreet/Alert.pm
@@ -177,12 +177,11 @@ sub email_alerts ($) {
$query->execute();
while (my $alert = $query->fetchrow_hashref) {
next unless (Cobrand::email_host($alert->{cobrand}));
- my $e = $alert->{parameter};
- my $n = $alert->{parameter2};
+ my $longitude = $alert->{parameter};
+ my $latitude = $alert->{parameter2};
$url = Cobrand::base_url_for_emails($alert->{cobrand}, $alert->{cobrand_data});
my ($site_restriction, $site_id) = Cobrand::site_restriction($alert->{cobrand}, $alert->{cobrand_data});
- my ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($e, $n, 'G');
- my $d = mySociety::Gaze::get_radius_containing_population($lat, $lon, 200000);
+ my $d = mySociety::Gaze::get_radius_containing_population($latitude, $longitude, 200000);
$d = int($d*10+0.5)/10;
my $testing_email_clause = "and problem.email <> '$testing_email'" if $testing_email;
my %data = ( template => $template, data => '', alert_id => $alert->{id}, alert_email => $alert->{email}, lang => $alert->{lang}, cobrand => $alert->{cobrand}, cobrand_data => $alert->{cobrand_data} );
@@ -195,7 +194,7 @@ sub email_alerts ($) {
$site_restriction
order by confirmed desc";
$q = dbh()->prepare($q);
- $q->execute($e, $n, $d, $alert->{whensubscribed}, $alert->{id}, $alert->{email});
+ $q->execute($latitude, $longitude, $d, $alert->{whensubscribed}, $alert->{id}, $alert->{email});
while (my $row = $q->fetchrow_hashref) {
dbh()->do('insert into alert_sent (alert_id, parameter) values (?,?)', {}, $alert->{id}, $row->{id});
$data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
@@ -303,9 +302,8 @@ sub generate_rss ($$$;$$$$) {
}
$item{description} .= ent("\n<br><a href='$cobrand_url'>Report on FixMyStreet</a>");
- if ($row->{easting} && $row->{northing}) {
- my ($lat,$lon) = mySociety::GeoUtil::national_grid_to_wgs84($row->{easting}, $row->{northing}, 'G');
- $item{georss} = { point => "$lat $lon" };
+ if ($row->{latitude} || $row->{longitude}) {
+ $item{georss} = { point => "$row->{latitude} $row->{longitude}" };
}
$rss->add_item( %item );
}
diff --git a/perllib/FixMyStreet/Geocode.pm b/perllib/FixMyStreet/Geocode.pm
index 4854411cf..0379169b8 100644
--- a/perllib/FixMyStreet/Geocode.pm
+++ b/perllib/FixMyStreet/Geocode.pm
@@ -37,40 +37,32 @@ BEGIN {
# of the site to diambiguate locations.
sub lookup {
my ($s, $q) = @_;
- my ($easting, $northing, $error);
+ my ($latitude, $longitude, $error);
if ($s =~ /^\d+$/) {
$error = 'FixMyStreet is a UK-based website that currently works in England, Scotland, and Wales. Please enter either a postcode, or a Great British street name and area.';
} elsif (mySociety::PostcodeUtil::is_valid_postcode($s)) {
my $location = mySociety::MaPit::call('postcode', $s);
unless ($error = Page::mapit_check_error($location)) {
- $easting = $location->{easting};
- $northing = $location->{northing};
+ $latitude = $location->{wgs84_lat};
+ $longitude = $location->{wgs84_lon};
}
} else {
- ($easting, $northing, $error) = FixMyStreet::Geocode::string($s, $q);
+ ($latitude, $longitude, $error) = FixMyStreet::Geocode::string($s, $q);
}
- return ($easting, $northing, $error);
+ return ($latitude, $longitude, $error);
}
sub geocoded_string_coordinates {
my ($js, $q) = @_;
- my ($easting, $northing, $error);
+ my ($latitude, $longitude, $error);
my ($accuracy) = $js =~ /"Accuracy" *: *(\d)/;
if ($accuracy < 4) {
$error = _('Sorry, that location appears to be too general; please be more specific.');
- } else {
-
- $js =~ /"coordinates" *: *\[ *(.*?), *(.*?),/;
- my $lon = $1; my $lat = $2;
- try {
- ($easting, $northing) = mySociety::GeoUtil::wgs84_to_national_grid($lat, $lon, 'G');
- } catch Error::Simple with {
- $error = shift;
- $error = _('That location does not appear to be in Britain; please try again.')
- if $error =~ /out of the area covered/;
- }
- }
- return ($easting, $northing, $error);
+ } elsif ( $js =~ /"coordinates" *: *\[ *(.*?), *(.*?),/ ) {
+ $longitude = $1;
+ $latitude = $2;
+ }
+ return ($latitude, $longitude, $error);
}
# string STRING QUERY
@@ -90,7 +82,7 @@ sub string {
my $url = 'http://maps.google.com/maps/geo?' . $s;
my $cache_dir = mySociety::Config::get('GEO_CACHE');
my $cache_file = $cache_dir . md5_hex($url);
- my ($js, $error, $easting, $northing);
+ my ($js, $error, $latitude, $longitude);
if (-s $cache_file) {
$js = File::Slurp::read_file($cache_file);
} else {
@@ -123,9 +115,9 @@ sub string {
# Northern Ireland, hopefully
$error = _("We do not cover Northern Ireland, I'm afraid, as our licence doesn't include any maps for the region.");
} else {
- ($easting, $northing, $error) = geocoded_string_coordinates($js, $q);
+ ($latitude, $longitude, $error) = geocoded_string_coordinates($js, $q);
}
- return ($easting, $northing, $error);
+ return ($latitude, $longitude, $error);
}
# list_choices
diff --git a/perllib/FixMyStreet/Map.pm b/perllib/FixMyStreet/Map.pm
index 12ecf78fe..0313fbe4f 100644
--- a/perllib/FixMyStreet/Map.pm
+++ b/perllib/FixMyStreet/Map.pm
@@ -14,7 +14,7 @@ use Problems;
use Cobrand;
use mySociety::Config;
use mySociety::Gaze;
-use mySociety::GeoUtil;
+use mySociety::GeoUtil qw(national_grid_to_wgs84);
use mySociety::Locale;
use mySociety::Web qw(ent NewURL);
@@ -23,20 +23,24 @@ load();
# This is yucky, but no-one's taught me a better way
sub load {
- my $type = mySociety::Config::get('MAP_TYPE');
+ my $type = mySociety::Config::get('MAP_TYPE');
my $class = "FixMyStreet::Map::$type";
eval "use $class";
+
+ # If we have an error die as it is a compile error rather than runtime error
+ die $@ if $@;
}
sub header {
- my ($q, $type) = @_;
+ my ( $q, $type ) = @_;
return '' unless $type;
my $cobrand = Page::get_cobrand($q);
- my $cobrand_form_elements = Cobrand::form_elements($cobrand, 'mapForm', $q);
- my $form_action = Cobrand::url($cobrand, '', $q);
+ my $cobrand_form_elements =
+ Cobrand::form_elements( $cobrand, 'mapForm', $q );
+ my $form_action = Cobrand::url( $cobrand, '', $q );
my $encoding = '';
- $encoding = ' enctype="multipart/form-data"' if $type==2;
+ $encoding = ' enctype="multipart/form-data"' if $type == 2;
my $pc = $q->param('pc') || '';
my $pc_enc = ent($pc);
return <<EOF;
@@ -47,49 +51,67 @@ $cobrand_form_elements
EOF
}
+=head2 map_features_easting_northing
+
+Wrapper around map_features which does the easting, northing to lat, lon
+conversion.
+
+=cut
+
+sub map_features_easting_northing {
+ my ( $q, $easting, $northing, $interval ) = @_;
+ my ( $lat, $lon ) = national_grid_to_wgs84( $easting, $northing, 'G' );
+ return map_features( $q, $lat, $lon, $interval );
+}
+
sub map_features {
- my ($q, $easting, $northing, $interval) = @_;
-
- my $min_e = $easting - 500;
- my $min_n = $northing - 500;
- my $mid_e = $easting;
- my $mid_n = $northing;
- my $max_e = $easting + 500;
- my $max_n = $northing + 500;
-
- # list of problems aoround map can be limited, but should show all pins
- my ($around_map, $around_map_list);
- if (my $around_limit = Cobrand::on_map_list_limit(Page::get_cobrand($q))) {
- $around_map_list = Problems::around_map($min_e, $max_e, $min_n, $max_n, $interval, $around_limit);
- $around_map = Problems::around_map($min_e, $max_e, $min_n, $max_n, $interval, undef);
- } else {
- $around_map = $around_map_list = Problems::around_map($min_e, $max_e, $min_n, $max_n, $interval, undef);
- }
+ my ( $q, $lat, $lon, $interval ) = @_;
+
+ # TODO - be smarter about calculating the surrounding square
+ # use deltas that are roughly 500m in the UK - so we get a 1 sq km search box
+ my $lat_delta = 0.00438;
+ my $lon_delta = 0.00736;
+
+ my $min_lat = $lat - $lat_delta;
+ my $max_lat = $lat + $lat_delta;
+
+ my $min_lon = $lon - $lon_delta;
+ my $max_lon = $lon + $lon_delta;
+
+ # list of problems around map can be limited, but should show all pins
+ my $around_limit #
+ = Cobrand::on_map_list_limit( Page::get_cobrand($q) ) || undef;
+
+ my @around_args = ( $min_lat, $max_lat, $min_lon, $max_lon, $interval );
+ my $around_map_list = Problems::around_map( @around_args, $around_limit );
+ my $around_map = Problems::around_map( @around_args, undef );
my $dist;
mySociety::Locale::in_gb_locale {
- my ($lat, $lon) = mySociety::GeoUtil::national_grid_to_wgs84($mid_e, $mid_n, 'G');
- $dist = mySociety::Gaze::get_radius_containing_population($lat, $lon, 200000);
+ $dist =
+ mySociety::Gaze::get_radius_containing_population( $lat, $lon,
+ 200000 );
};
- $dist = int($dist*10+0.5)/10;
+ $dist = int( $dist * 10 + 0.5 ) / 10;
- my $limit = 20;
- my @ids = map { $_->{id} } @$around_map_list;
- my $nearby = Problems::nearby($dist, join(',', @ids), $limit, $mid_e, $mid_n, $interval);
+ my $limit = 20;
+ my @ids = map { $_->{id} } @$around_map_list;
+ my $nearby = Problems::nearby( $dist, join( ',', @ids ),
+ $limit, $lat, $lon, $interval );
- return ($around_map, $around_map_list, $nearby, $dist);
+ return ( $around_map, $around_map_list, $nearby, $dist );
}
sub compass ($$$) {
- my ($q, $x, $y) = @_;
+ my ( $q, $x, $y ) = @_;
my @compass;
- for (my $i=$x-1; $i<=$x+1; $i++) {
- for (my $j=$y-1; $j<=$y+1; $j++) {
- $compass[$i][$j] = NewURL($q, x=>$i, y=>$j);
+ for ( my $i = $x - 1 ; $i <= $x + 1 ; $i++ ) {
+ for ( my $j = $y - 1 ; $j <= $y + 1 ; $j++ ) {
+ $compass[$i][$j] = NewURL( $q, x => $i, y => $j );
}
}
my $recentre = NewURL($q);
- my $host = Page::base_url_with_lang($q, undef);
+ my $host = Page::base_url_with_lang( $q, undef );
return <<EOF;
<table cellpadding="0" cellspacing="0" border="0" id="compass">
<tr valign="bottom">
diff --git a/perllib/FixMyStreet/Map/Tilma/Original.pm b/perllib/FixMyStreet/Map/Tilma/Original.pm
index 5772f6ccd..5f5a102ac 100644
--- a/perllib/FixMyStreet/Map/Tilma/Original.pm
+++ b/perllib/FixMyStreet/Map/Tilma/Original.pm
@@ -13,6 +13,12 @@ use LWP::Simple;
use Cobrand;
use mySociety::Web qw(ent NewURL);
+use mySociety::GeoUtil qw(national_grid_to_wgs84);
+
+sub _ll_to_en {
+ my ($lat, $lon) = @_;
+ return mySociety::GeoUtil::wgs84_to_national_grid( $lat, $lon, 'G' );
+}
sub header_js {
return '
@@ -22,7 +28,7 @@ sub header_js {
# display_map Q PARAMS
# PARAMS include:
-# EASTING, NORTHING for the centre point of the map
+# latitude, longitude for the centre point of the map
# TYPE is 1 if the map is clickable, 2 if clickable and has a form upload,
# 0 if not clickable
# PINS is array of pins to show, location and colour
@@ -36,6 +42,18 @@ sub _display_map {
$mid_point = 189;
}
+ # convert map center point to easting, northing
+ ( $params{easting}, $params{northing} ) =
+ _ll_to_en( $params{latitude}, $params{longitude} );
+
+ # FIXME - convert all pins to lat, lng
+ # all the pins are currently [lat, lng, colour] - convert them
+ foreach my $pin ( @{ $params{pins} ||= [] } ) {
+ my ( $lat, $lon ) = ( $pin->[0], $pin->[1] );
+ my ( $e, $n ) = _ll_to_en( $lat, $lon );
+ ( $pin->[0], $pin->[1] ) = ( $e, $n );
+ }
+
# X/Y tile co-ords may be overridden in the query string
my @vars = qw(x y);
my %input = map { $_ => $q->param($_) || '' } @vars;
@@ -154,10 +172,14 @@ sub map_pins {
my $e = FixMyStreet::Map::tile_to_os($x);
my $n = FixMyStreet::Map::tile_to_os($y);
- my ($around_map, $around_map_list, $nearby, $dist) = FixMyStreet::Map::map_features($q, $e, $n, $interval);
+
+ my ( $around_map, $around_map_list, $nearby, $dist ) =
+ FixMyStreet::Map::map_features_easting_northing( $q, $e, $n, $interval );
my $pins = '';
foreach (@$around_map) {
+ ( $_->{easting}, $_->{northing} ) =
+ _ll_to_en( $_->{latitude}, $_->{longitude} );
my $px = FixMyStreet::Map::os_to_px($_->{easting}, $sx);
my $py = FixMyStreet::Map::os_to_px($_->{northing}, $sy, 1);
my $col = $_->{state} eq 'fixed' ? 'green' : 'red';
@@ -165,6 +187,8 @@ sub map_pins {
}
foreach (@$nearby) {
+ ( $_->{easting}, $_->{northing} ) =
+ _ll_to_en( $_->{latitude}, $_->{longitude} );
my $px = FixMyStreet::Map::os_to_px($_->{easting}, $sx);
my $py = FixMyStreet::Map::os_to_px($_->{northing}, $sy, 1);
my $col = $_->{state} eq 'fixed' ? 'green' : 'red';
@@ -196,10 +220,30 @@ sub tile_to_px {
sub os_to_tile {
return $_[0] / SCALE_FACTOR;
}
+
sub tile_to_os {
return int($_[0] * SCALE_FACTOR + 0.5);
}
+=head2 tile_xy_to_wgs84
+
+ ($lat, $lon) = tile_xy_to_wgs84( $x, $y );
+
+Takes the tile x,y and converts to lat, lon.
+
+=cut
+
+sub tile_xy_to_wgs84 {
+ my ( $x, $y ) = @_;
+
+ my $easting = tile_to_os($x);
+ my $northing = tile_to_os($y);
+
+ my ( $lat, $lon ) = national_grid_to_wgs84( $easting, $northing, 'G' );
+ return ( $lat, $lon );
+}
+
+
sub click_to_tile {
my ($pin_tile, $pin, $invert) = @_;
$pin -= TILE_WIDTH while $pin > TILE_WIDTH;
@@ -219,6 +263,14 @@ sub click_to_os {
return ($easting, $northing);
}
+# 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 ( $easting, $northing ) = FixMyStreet::Map::click_to_os(@_);
+ my ( $lat, $lon ) = national_grid_to_wgs84( $easting, $northing, 'G' );
+ return ( $lat, $lon );
+}
+
# Given (E,N) and potential override (X,Y), return the X/Y tile for the centre
# of the map (either to get the point near the middle, or the override X,Y),
# and the pixel co-ords of the point, relative to that map.