User:SunCobalt/OpenLayers Suche

From OpenStreetMap Wiki
Jump to: navigation, search

OpenLayers mit Nominatim Suche

anbei ein einfaches Beispiel, wie man mit OpenLayers und dem MapQuest Nominatim Service eine Webseite mit Suche installiert. Die Suche läßt sich so gestalten, dass die Ergebnisse primär in einer bestimmten Sprache (name:xx) angezeigt und auch die Ergebniskategorien (Stadt, Restaurant etc) übersetzt werden. Ein besonderer Dank geht an Max User:Maxbe, der dieses erst möglich gemacht hat. Die index.html ruft das php-Skript mapquestjs.php auf. Die Kategorieübersetzungen werden in der Datei nominatim-i8n.csv geregelt. php5-curl muss installiert sein

Fehlersuche

Fehler in den Suchergebnissen

Um ggf Fehler in OSM zu korrigieren zu können, kann es hilfreich sein, Details zu den Ergebnissen und deren Beziehungen zur Hierachie zu wissen. MapQuest Nominatim Dort dann links beim gewünschten Ergebnis auf Details klicken.

Suche funktioniert nicht

Sein eigenes php Skript kann man testen, indem man http://deine.domain.de/mapquestjs.php?q=Berlin im Browser eingibt. Das Ergbnis im Browser müsste für Berlin so aussehen: 13.4023051674614 52.5014783395417 Administrative: Berlin Administrative: Berlin 13.4023271 52.5015955 State: Berlin, Germany State: Berlin, Germany, Europe 13.3888548 52.5170397 City: Berlin, Berlin, Germany City: Berlin, Berlin, Stadt, Mitte, Berlin, Germany, Europe

index.html

<html>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
  <head>
    <title>OpenStreetMap</title>
    <style type="text/css">
      html, body {
          font-family: sans-serif;
          height: 100%;
          width:  100%;
          padding:0;
          margin: 0;
          background-color:#FFF8C6;
      }
      div#sidebar   { width:20%; height: 100%;margin: 0; padding-left: 1em; padding-right: 2em;
                      overflow: hidden; float:left;background-color:#FFF8C6;}
      div#mapdiv    { width:75%; height: 100%;min-width:200px;margin: 0; float:right;
                      right:0;top:0;position:fixed;;background-color:#B3C6D4;}
    </style>
    <script src="http://toolserver.org/~osm/libs/openlayers/latest/OpenLayers.js"></script>
    <script>

      OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5;

      var map,Point,vectorLayer;

      function jumptolonlat(lon,lat){
       if(!vectorLayer.getVisibility()){vectorLayer.setVisibility(true)}
       var LonLat = new OpenLayers.LonLat(lon,lat).transform(new OpenLayers.Projection("EPSG:4326"),map.getProjectionObject());
       map.setCenter(LonLat,10);
       Point.move(LonLat);
       return false;
      }


      function fragmapquest(){

// ************ change your country code for language localisation
       var lang="en";
       url="mapquestjs.php?q="+document.getElementById("query").value+"&limit=6"+"&lang="+lang;
       var http = new XMLHttpRequest();
       http.open("GET",url,false);
       http.send(null);
       zeile=http.responseText.split("\n");
       resultdiv = document.getElementById("result");
       if(zeile.length<=1){
        resultdiv.innerHTML="No Search Results for \""+document.getElementById("query").value+"\"";
       }else{
        resultdiv.innerHTML="Search Results \""+document.getElementById("query").value+"\"<ul>";
        i=0;
        for(i=0;i<zeile.length;i++){
         spalte=zeile[i].split("\t");
         if((spalte[0]*spalte[0]>0)||(spalte[1]*spalte[1]>0)){
          if(i==0){jumptolonlat(spalte[0],spalte[1]);}
          displaytext=spalte[2];
          resultdiv.innerHTML=resultdiv.innerHTML+"<font size=2><li><a href=# onmouseup=\"jumptolonlat("+spalte[0]+","+spalte[1]+");\">"+displaytext+"</a></li><br>";
          }
         }
         resultdiv.innerHTML=resultdiv.innerHTML+"</ul>";
        }
        return false;
       }



      function init() {
            var options = {
                projection: new OpenLayers.Projection("EPSG:900913"),
                displayProjection: new OpenLayers.Projection("EPSG:4326"),
                units: "m",
                resolutions : [156543.03390000001, 78271.516950000005, 39135.758475000002, 19567.879237500001, 9783.9396187500006, 4891.9698093750003, 2445.98490468750],
                maxResolution: 156543.0339,
                maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
                                                 20037508.34, 20037508.34),
                 controls: [
                        new OpenLayers.Control.Navigation(),
                        new OpenLayers.Control.LayerSwitcher(),
                        new OpenLayers.Control.PanZoomBar(),
                        new OpenLayers.Control.Attribution(),
                        new OpenLayers.Control.Permalink(),
                        new OpenLayers.Control.MousePosition(),
                        new OpenLayers.Control.KeyboardDefaults(),
                        new OpenLayers.Control.ScaleLine({geodesic:true})]
            };
         map = new OpenLayers.Map('mapdiv', options);

         layerMapnik  = new OpenLayers.Layer.OSM("Mapnik");

        map.addLayers([layerMapnik]);

        var centerLonLat = new OpenLayers.LonLat(12.30,51.15).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
        if (!map.getCenter())
                map.setCenter (centerLonLat, 7);

       vectorLayer = new OpenLayers.Layer.Vector("search result",{visibility: false});

// *****************Icon, das das Resultat auf der Karte markiert -> arrow.png ggf austauschen

       pointstyle  = {externalGraphic:"./arrow.png", graphicHeight: 22, graphicWidth: 25, graphicXOffset: -25, graphicYOffset: -21};
       Point = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0),null,pointstyle);
       vectorLayer.addFeatures([Point]);
       map.addLayer(vectorLayer);
      }
    </script>
  </head>
  <body onload="init();">
    <div id="sidebar">
     <br>
     <center><b>OpenStreetMap</b></center>

//****OSM Logo besorgen oder Code löschen

     <img src="osm_logo.png" width="120" height="120"/>

     <br>
     <form action="" method=get onsubmit="fragmapquest();return false;"><input type="text" id="query" name="q" size="20"><br>
     <input type="submit" value="Search">
     <br><font size="-2">Nominatim Search Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a></font>
     </form>
     <div id="result"></div>
    </div>
    <div id="mapdiv">
</div>
  </body>
</html>

mapquestjs.php

<?php

/*
  Description: mapquestjs.php?q=QUERY[&limit=N][&lang=LANG]
               parses the xml response from mapquest and delivers a tab delimited list of serch results

  Parameters:  q=QUERY:    an urldecoded search string,
                           eg "Berlin" or "Bahnhof Starnberg" or "Brasil" or "Hotel London" or "Heinestraße, Würzburg"
               limit=N:    the maximum number of search results
                           default: 3
               lang=LANG:  a comma separated list of the preferred response language
                           eg "de,en,ru" or "de" or  "fr-FR,de-DE;q=0.5"
                           default: the ACCEPT_LANGUAGE-Parameter sent by the browser


  Result:          LON<tab>LAT<tab>Shortname<tab>Longname<CR>
                   LON<tab>LAT<tab>Shortname<tab>Longname<CR>
                   LON<tab>LAT<tab>Shortname<tab>Longname<CR>

                   Shortname is something estimated from the type of the search result (estimated means sometimes too short...)
                   Longname  is the "DISPLAY_NAME" delivered by mapquest/nominatim (very verbose and often too long...)

  Error response:  None, just no result.

  Needs CURL and PHP...
*/

/*
 Read "nominatim-i8n.csv" and get an array
   $translation['peak']['en']='peak';
   $translation['peak']['de']='Berg';
   $translation['peak']['it']='Montagna';

 for file format of nominatim-i8n.csv see comments there
*/
  $translation['dummy']['en']='dummy';
  $fd=fopen("nominatim-i8n.csv","r");
  if($fd){
   $i=0;
   while(!feof($fd)){
    $line=trim(fgets($fd,1000));
    if(($line)&&($line[0]!="#")&&(strlen($line)>2)){
     $i++;
     if($i==1){
      $lang=preg_split("/:/",strtolower($line));
      for($j=0;$j<count($lang);$j++){$lang[$j]=trim($lang[$j]);}
     }else{
      $trans=preg_split("/:/",$line);
      for($j=0;$j<count($trans);$j++){
       $trans[$j]=trim($trans[$j]);
       $translation[$trans[0]][$lang[$j]]=$trans[$j];
      }
     }
    }
   }
   fclose($fd);
  }
/* get parameters, set defaults */

  $query=urlencode($_GET["q"]);
  $limit=urlencode($_GET["limit"]);
  $lang=urlencode($_GET["lang"]);
  if($limit==0){$limit=3;}
  if($lang==""){$lang=$_SERVER['HTTP_ACCEPT_LANGUAGE'];}

/* open mapquestapi.com and get results  */

  $crl = curl_init();
  $url="http://open.mapquestapi.com/nominatim/v1/search?q=".$query."&format=xml&polygon=0&addressdetails=1&limit=".$limit."&accept-language=".$lang;
  $lang=substr(strtolower($lang),0,2);
  curl_setopt ($crl, CURLOPT_URL,$url);
  curl_setopt ($crl, CURLOPT_RETURNTRANSFER, 1);
  $ret = curl_exec($crl);
  curl_close($crl); /* ; fehlte */

/* Parse XML data into an array structure */

  $xml_parser = xml_parser_create();
  xml_parse_into_struct($xml_parser, $ret, $vals, $index);
  xml_parser_free($xml_parser);


/* Loop throug each array

   <Place level=2> opens a record and contains lon,lat,display_name....
   then follow some level=3-Items with county,city,peak,road,hotel...
   </Place level=2> closes this record

   <place type> is replaced by translation if available
*/
  foreach($vals as $element){
   if(($element['tag']=="PLACE")&&($element['type']=="open")&&($element['level']=="2")){
    $type=$longname=$shortname="";$lon=$lat=0;
    $lon=$element['attributes']['LON'];
    $lat=$element['attributes']['LAT'];
    $longname=$element['attributes']['DISPLAY_NAME'];
    $class=$element['attributes']['CLASS'];
    $type=strtolower($element['attributes']['TYPE']);
    if($translation[$type][$lang]!="") {$transtype=$translation[$type][$lang];}
    else {$transtype=$type;}
   }
/* Try to interprete level-3-tags to build a shortname */

   if($element['level']=="3"){
    if(($element['tag']==strtoupper($type))||(($element['tag']=='ROAD')&&($class=='highway'))){
     $shortname=$shortname." ".$element['value'];
    }else{
     if(($element['tag']=='VILLAGE')){$shortname=$shortname.", ".$element['value'];}
     if(($element['tag']=='TOWN'))   {$shortname=$shortname.", ".$element['value'];}
     if(($element['tag']=='CITY'))   {$shortname=$shortname.", ".$element['value'];}
     if(($element['tag']=='STATE'))  {$shortname=$shortname.", ".$element['value'];}
     if(($element['tag']=='COUNTRY')){$shortname=$shortname.", ".$element['value'];}
    }
   }

/* end of record: print result */

   if(($element['tag']=="PLACE")&&($element['type']=="close")&&($element['level']=="2")){
    $shortname=preg_replace("/^,/","",$shortname);
    print "$lon\t$lat\t".ucfirst($transtype).": $shortname\t".ucfirst($type).": $longname\n";
    $type=$longname=$shortname="";$lon=$lat=0;
   }
  }
 exit();
?>

/* end */

nominatim-i8n.csv

###########################################################################
#
# nominatim-i8n.csv: Internationalisation for nominatim search results
#                    Translation of <place type="">-Attributes
#
# First line contains a list of all supported languages (ISO 639-1) with
# default (en) as first row. Only 2-char-codes please, "de-ch" or "en-us"
# is not supported.
#
# each following line contains the english expression as first row and then
# the translations for each language. These lines don't have to be
# complete, if some translation is missing, we will take the default
# value.
#
# Delimiter is ":", empty fields (like "city:Stadt::Ville:Ciudad") are ok,
# emty lines are ok, "#" as first char flags a comment
#
# Character set is UTF-8 (in fact the character set is not important, but
# the browser has to interpret this and all other results of nominatim
# search are UTF-8. HTML-entities like in "Stra&szlig;e" are also ok)
#
###########################################################################

#
# At first the supported languages
#

en               :de                            :hu                     :sr

#
# Roads
#
bridleway        : Reitweg                      : lovaglóösvény         : koњска стаза
crossing         : Kreuzung                     : kereszteződés         : раскрсница
cycleway         : Radweg                       : kerékpárút            : бициклистичка стаза

.....

Arrow.png (Datei umbenennen oder Code ändern) Arrow OL Search.png

osm_logo.png (Datei umbenennen oder Code ändern) Mag map-120x120.png

Download Beispieldateien

Download Zip File