[NUUG fiksgatami] Idé til å identifisere veieier med OpenStreetmap

Petter Reinholdtsen pere at hungry.com
Thu Apr 14 09:30:07 CEST 2011


[Petter Reinholdtsen]
> Alternativt kan vi sende til begge, men legge inn informasjon i
> eposten om hva vi har gjettet oss frem til av operatør for veien.

Jeg har videreforedlet perlkoden og patchet inn i bin/send-reports.
Vedlagt er et utkast til patch som gir følgende snutt i
eksempelrapportene på fiksgatami-dev.nuug.no:

     Dear Vennesla,

     A user of FixMyStreet has submitted the following report of a
     local problem that they believe might require your attention.

     To view a map of the precise location of this issue, or to
     provide an update on the problem, please visit the following
     link:

         http://fiksgatami-dev.nuug.no/report/57

     This web page also contains a photo of the problem, provided by
     the user.

     ----------

     Name: =D8rjan V=F8llestad

     Email: orjanv (at) gmail.com

     Category: Dumpet skrot

     Subject: Ute omr=E5det

     Details: Cccccccccccc

     Latitude: 58.265957

     Longitude: 7.975955

     Nearest named road to the pin placed on the map (automatically
     generated using OpenStreetmap): Sentrumsvegen (FV66)

     Guessed road operator: Statens Vegvesen

Ser dette greit ut?  Hvis dere synes dette ser greit ut, er neste steg
å sjekke med Matthew hva han synes.

Det nest nederste avsnittet kommer kun hvis Nominatim-søket returnerer
en vei, og det nederste avsnittet kommer kun med hvis koen tror
Statens vegvesen er operatør for veien.

Patchen bør fortsatt justeres.  F.eks. tror jeg de OSM-relaterte
funksjonene bør flyttes til perllib/FixMyStreet/Map/OSM.pm i stedet
for å ligge direkte i send-reports.

Jeg tror en slik tilnærming kombinert med at vi sender både til
kommunen og vegvesenet vil gjøre det enklere for mottaker å gjette om
det er en sak de skal ha eller ikke, synliggjøre at bedre datagrunnlag
vil gjøre oss mer treffsikker, samt gjøre at kommunene og vegvesenet
blir mer motivert til å komme med korreksjoner rundt veieierskap og
navn når de ser at de i neste omgang får bedre meldinger når vi
korrigerer OSM basert på tilbakemeldingene.

Vennlig hilsen,
-- 
Petter Reinholdtsen
-------------- next part --------------
diff --git a/bin/send-reports b/bin/send-reports
index 8e6d2d1..e1e8290 100755
--- a/bin/send-reports
+++ b/bin/send-reports
@@ -46,6 +46,12 @@ BEGIN {
     );
 }
 
+use XML::Simple;
+use LWP::Simple;
+use Data::Dumper;
+my $nominatimbase = "http://nominatim.openstreetmap.org/";
+my $osmbase       = "http://www.openstreetmap.org/api/";
+
 # Set up site, language etc.
 my ($verbose, $nomail) = CronFns::options();
 my $base_url = mySociety::Config::get('BASE_URL');
@@ -110,9 +116,8 @@ foreach my $row (@$unsent) {
         $h{easting_northing}                             #
           = "Easting: $h{easting}\n\n"                   #
           . "Northing: $h{northing}\n\n";
-
-        $h{closest_address} = find_closest($row, $h{latitude}, $h{longitude});
     }
+    $h{closest_address} = find_closest($row, $h{latitude}, $h{longitude});
     $h{closest_address_machine} = $h{closest_address};
 
     my (@to, @recips, $template, $areas_info);
@@ -274,6 +279,72 @@ if ($verbose) {
     }
 }
 
+sub lookupNominatim {
+    my ($latitude, $longitude) = @_;
+    my $url =
+    "${nominatimbase}reverse?format=xml&zoom=16&lat=$latitude&lon=$longitude";
+    my $j = LWP::Simple::get($url);
+    if ($j) {
+        my $ref = XMLin($j);
+#        print STDERR "URL: $url\n";
+#        print STDERR Dumper($ref);
+        return $ref;
+    } else {
+        print STDERR "No reply from $url\n";
+    }
+    return undef;
+}
+sub getOSMWayTags {
+    my $wayid = shift;
+    my $url = "${osmbase}0.6/way/$wayid";
+#    print STDERR "URL: $url\n";
+    my $j = LWP::Simple::get($url);
+    if ($j) {
+        my $ref = XMLin($j);
+#        print STDERR Dumper($ref);
+        my %tags;
+        map { $tags{$_->{'k'}} = $_->{'v'} } @{$ref->{way}->{tag}};
+        return \%tags;
+    } else {
+        print STDERR "No reply from $url\n";
+    }
+    return undef;
+}
+
+sub guessRoadOperator {
+    my $inforef = shift;
+    my $highway = $inforef->{highway} || "unknown";
+    my $ref =  $inforef->{ref} || "unknown";
+
+    my $operator;
+
+    if ($highway eq "trunk"
+        || $highway eq "primary"
+        || $ref =~ m/E \d+/
+        || $ref =~ m/Fv\d+/i
+        ) {
+        $operator = "Statens Vegvesen";
+    }
+#    print STDERR "Guessing operator $operator\n" if defined $operator;
+    return $operator;
+}
+
+sub getNearestRoadTags {
+    my ($latitude, $longitude) = @_;
+    my $inforef = lookupNominatim($latitude, $longitude);
+    if ('way' eq $inforef->{result}->{osm_type}) {
+
+        my $osmtags = getOSMWayTags($inforef->{result}->{osm_id});
+#        print STDERR Dumper $osmtags;
+        unless (exists $osmtags->{operator}) {
+            $osmtags->{operatorguess} = guessRoadOperator($osmtags);
+            delete $osmtags->{operator};
+        }
+        return $osmtags;
+    }
+    return undef;
+}
+
 sub _get_district_for_contact {
     my ( $lat, $lon ) = @_;
     my $district =
@@ -353,24 +424,55 @@ sub find_closest {
     return '' unless $row->{used_map};
 
     # Get nearest road-type thing from Bing
-    my $url = "http://dev.virtualearth.net/REST/v1/Locations/$latitude,$longitude?c=en-GB&key=" . mySociety::Config::get('BING_MAPS_API_KEY');
+    my $bingkey;
+    try {
+        $bingkey = mySociety::Config::get('BING_MAPS_API_KEY');
+    } otherwise {
+        my $e = shift;
+        # Ignoring missing BING key, it is optional.
+    };
+    if ($bingkey) {
+        my $url = "http://dev.virtualearth.net/REST/v1/Locations/$latitude,$longitude?c=en-GB&key=$bingkey";
     my $j = LWP::Simple::get($url);
     if ($j) {
         $j = JSON->new->utf8->allow_nonref->decode($j);
         if ($j->{resourceSets}[0]{resources}[0]{name}) {
-            $str .= "Nearest road to the pin placed on the map (automatically generated by Bing Maps): $j->{resourceSets}[0]{resources}[0]{name}\n\n";
+                $str .= sprintf(_("Nearest road to the pin placed on the map (automatically generated by Bing Maps): %s\n\n"),
+                                $j->{resourceSets}[0]{resources}[0]{name});
+            }
         }
     }
 
     # Get nearest postcode from Matthew's random gazetteer (put in MaPit? Or elsewhere?)
-    $url = "http://gazetteer.dracos.vm.bytemark.co.uk/point/$latitude,$longitude.json";
-    $j = LWP::Simple::get($url);
+    if ( mySociety::Config::get('COUNTRY') eq 'GB' ) {
+        my $url = "http://gazetteer.dracos.vm.bytemark.co.uk/point/$latitude,$longitude.json";
+        my $j = LWP::Simple::get($url);
     if ($j) {
         $j = JSON->new->utf8->allow_nonref->decode($j);
         if ($j->{postcode}) {
-            $str .= "Nearest postcode to the pin placed on the map (automatically generated): $j->{postcode}[0] ($j->{postcode}[1]m away)\n\n";
+                $str .= sprintf(_("Nearest postcode to the pin placed on the map (automatically generated): %s (%sm away)\n\n"),
+                                $j->{postcode}[0], $j->{postcode}[1]);
+            }
+        }
         }
+    if ( mySociety::Config::get('COUNTRY') eq 'NO' ) {
+        my $osmtags = getNearestRoadTags($latitude, $longitude);
+        if ($osmtags) {
+            my ($name, $ref) = ('','');
+            $name =  $osmtags->{name} if exists $osmtags->{name};
+            $ref = " ($osmtags->{ref})" if exists $osmtags->{ref};
+            if ($name || $ref) {
+                $str .= sprintf(_("Nearest named road to the pin placed on the map (automatically generated using OpenStreetmap): %s%s\n\n"),
+                                $name, $ref);
     }
+            my $operator = $osmtags->{operator} || $osmtags->{operatorguess};
+            if ($operator) {
+                $str .= sprintf(_("Guessed road operator: %s\n\n"),
+                                $operator);
+            }
+        }
+    }
+
     return $str;
 }
 


More information about the fiksgatami mailing list