diff options
author | Struan Donald <struan@exo.org.uk> | 2012-08-22 10:57:10 +0100 |
---|---|---|
committer | Struan Donald <struan@exo.org.uk> | 2012-08-22 10:57:10 +0100 |
commit | 2e0a4e8ec45579e4e5c9cf8aa123d5ab215b9703 (patch) | |
tree | c13e3c59b686e01460dc7960547f7e9c53c288bd /perllib/FixMyStreet/Geocode/OSM.pm | |
parent | b99c5ff97b29a27eeba52ed24385ac30388e875c (diff) | |
parent | 88a7d38dffa3dabdf0f85573b254cea9c8ab232b (diff) |
Merge remote-tracking branch 'origin/master' into fmb-read-only
Conflicts:
.gitignore
bin/make_css
conf/general.yml-example
perllib/FixMyStreet/App/Controller/Council.pm
perllib/FixMyStreet/App/Controller/Report/New.pm
perllib/FixMyStreet/Cobrand/Default.pm
templates/web/default/around/around_index.html
templates/web/default/index.html
templates/web/emptyhomes/index.html
templates/web/fixmystreet/around/around_index.html
templates/web/fixmystreet/index.html
web/fixmystreet_app_cgi.cgi
web/fixmystreet_app_fastcgi.cgi
Diffstat (limited to 'perllib/FixMyStreet/Geocode/OSM.pm')
-rw-r--r-- | perllib/FixMyStreet/Geocode/OSM.pm | 69 |
1 files changed, 64 insertions, 5 deletions
diff --git a/perllib/FixMyStreet/Geocode/OSM.pm b/perllib/FixMyStreet/Geocode/OSM.pm index b1becaa7a..ba939b443 100644 --- a/perllib/FixMyStreet/Geocode/OSM.pm +++ b/perllib/FixMyStreet/Geocode/OSM.pm @@ -11,20 +11,79 @@ package FixMyStreet::Geocode::OSM; use warnings; use strict; -use Memcached; -use mySociety::Config; +use Digest::MD5 qw(md5_hex); +use Encode; +use File::Slurp; +use File::Path (); use LWP::Simple; +use Memcached; use XML::Simple; my $osmapibase = "http://www.openstreetmap.org/api/"; my $nominatimbase = "http://nominatim.openstreetmap.org/"; +# string STRING CONTEXT +# Looks up on Nominatim, and caches, a user-inputted location. +# Returns array of (LAT, LON, ERROR), where ERROR is either undef, a string, or +# an array of matches if there are more than one. The information in the query +# may be used to disambiguate the location in cobranded versions of the site. +sub string { + my ( $s, $c, $params ) = @_; + $s .= '+' . $params->{town} if $params->{town} and $s !~ /$params->{town}/i; + my $url = "${nominatimbase}search?"; + my %query_params = ( + q => $s, + format => 'json', + #'accept-language' => '', + email => 'support' . chr(64) . 'fixmystreet.com', + ); + $query_params{viewbox} = $params->{bounds}[1] . ',' . $params->{bounds}[2] . ',' . $params->{bounds}[3] . ',' . $params->{bounds}[0] + if $params->{bounds}; + $query_params{countrycodes} = $params->{country} + if $params->{country}; + $url .= join('&', map { "$_=$query_params{$_}" } keys %query_params); + + my $cache_dir = FixMyStreet->config('GEO_CACHE') . 'osm/'; + my $cache_file = $cache_dir . md5_hex($url); + my $js; + if (-s $cache_file) { + $js = File::Slurp::read_file($cache_file); + } else { + $js = LWP::Simple::get($url); + $js = encode_utf8($js) if utf8::is_utf8($js); + File::Path::mkpath($cache_dir); + File::Slurp::write_file($cache_file, $js) if $js; + } + + if (!$js) { + return { error => _('Sorry, we could not parse that location. Please try again.') }; + } + + $js = JSON->new->utf8->allow_nonref->decode($js); + + my ( $error, @valid_locations, $latitude, $longitude ); + foreach (@$js) { + # These co-ordinates are output as query parameters in a URL, make sure they have a "." + ( $latitude, $longitude ) = ( $_->{lat}, $_->{lon} ); + mySociety::Locale::in_gb_locale { + push (@$error, { + address => $_->{display_name}, + latitude => sprintf('%0.6f', $latitude), + longitude => sprintf('%0.6f', $longitude) + }); + }; + push (@valid_locations, $_); + } + + return { latitude => $latitude, longitude => $longitude } if scalar @valid_locations == 1; + return { error => $error }; +} -sub lookup_location { +sub reverse_geocode { my ($latitude, $longitude, $zoom) = @_; my $url = "${nominatimbase}reverse?format=xml&zoom=$zoom&lat=$latitude&lon=$longitude"; - my $key = "OSM:lookup_location:$url"; + my $key = "OSM:reverse_geocode:$url"; my $result = Memcached::get($key); unless ($result) { my $j = LWP::Simple::get($url); @@ -74,7 +133,7 @@ sub get_object_tags { # http://www.geonames.org/maps/osm-reverse-geocoder.html#findNearbyStreetsOSM sub get_nearest_road_tags { my ( $cobrand, $latitude, $longitude ) = @_; - my $inforef = lookup_location($latitude, $longitude, 16); + my $inforef = reverse_geocode($latitude, $longitude, 16); if (exists $inforef->{result}->{osm_type} && 'way' eq $inforef->{result}->{osm_type}) { my $osmtags = get_object_tags('way', |