2013-04-23 107 views
0

我有一個簡單的PHP函數得到的最接近附近的城市從給定的緯度和經度:查找附近的大型城市GEONAMES

function findCity($lat, $lng, $username) { 
     $json_url = "http://api.geonames.org/findNearbyPlaceNameJSON?lat=" . $lat . "&lng=" . $lng . "&username=" . $username; 
     $json = file_get_contents($json_url); 
     $json = str_replace('}, 

      ]', "} 

      ]", $json); 
     $data = json_decode($json); 

     echo "<pre>"; 
    print_r($data); 
    echo "</pre>"; 
    } 

此方法返回與緯度如下:51.992和長:4.89

stdClass Object 
(
    [geonames] => Array 
     (
      [0] => stdClass Object 
       (
        [countryName] => Netherlands 
        [adminCode1] => 11 
        [fclName] => city, village,... 
        [countryCode] => NL 
        [lng] => 4.876389 
        [fcodeName] => populated place 
        [distance] => 1.42349 
        [toponymName] => Langerak 
        [fcl] => P 
        [name] => Langerak 
        [fcode] => PPL 
        [geonameId] => 2751924 
        [lat] => 51.931667 
        [adminName1] => South Holland 
        [population] => 0 
       ) 

     ) 

) 

這將返回最近的城市,但我正在尋找像this之類的東西。只有最近的大城市纔會被退回。這可能嗎?或者還有其他的解決方案來解決這個問題我已閱讀過Google地理編碼API,但我們無法使用它,因爲我們沒有使用Google地圖來顯示結果。 (注:地址解析API只能與谷歌地圖結合使用;地址解析結果,而不在地圖上顯示他們是被禁止Source

我知道這是不是一個實際的程序員的問題,但由於GEONAMES論壇沒有真正活躍,我想我會在這裏發佈。

+0

如果您使用的是Apache,您可以試試geoip。 http://www.maxmind.com/app/mod_geoip – 2013-04-23 15:52:52

+0

@BryanPotts,我打算使用這種方法通過搜索緯度和長元數據來查找圖像的位置(來自地球,空間不足)給出圖片。 – Jef 2013-04-23 16:22:39

回答

1

您需要列出最大的城市。我沒有找到一個關於geonames的API調用(可能試試freebase api for sorting by city relevance)。因爲你展示的例子列表是簡短的靜態代碼,你可以用它來代碼化嗎?如果是這樣,你可以使用如下的內容:

/* 
* Haversine formula 
* from: http://rosettacode.org/wiki/Haversine_formula#PHP 
*/ 

class POI { 
    private $latitude; 
    private $longitude; 
    public function __construct($latitude, $longitude) { 
     $this->latitude = deg2rad($latitude); 
     $this->longitude = deg2rad($longitude); 
    } 
    public function getLatitude() {return $this->latitude;} 
    public function getLongitude(){return $this->longitude;} 
    public function getDistanceInMetersTo(POI $other) { 
     $radiusOfEarth = 6371000;// Earth's radius in meters. 
     $diffLatitude = $other->getLatitude() - $this->latitude; 
     $diffLongitude = $other->getLongitude() - $this->longitude; 
     $a = sin($diffLatitude/2) * sin($diffLatitude/2) + 
      cos($this->latitude) * cos($other->getLatitude()) * 
      sin($diffLongitude/2) * sin($diffLongitude/2); 
     $c = 2 * asin(sqrt($a)); 
     $distance = $radiusOfEarth * $c; 
     return $distance; 
    } 
} 


class bigcity 
{ 
    public $name; 
    public $lat; 
    public $long; 

    function __construct($name,$lat,$long) 
    { 
     $this->name=$name; 
     $this->lat=$lat; 
     $this->long=$long; 
    }  
} 

function getbigcities() 
{ 
    $bigcities = array(); 
    $bigcities[] = new bigcity('Amsterdam',52.374 ,4.89); 
    $bigcities[] = new bigcity('Eindhoven',51.441 ,5.478); 
    $bigcities[] = new bigcity('Groningen',53.219 ,6.567); 
    return $bigcities; 
} 


function findCity($lat, $lng) 
{ 
    $userinput = new POI($lat,$lng); 
    $bigcities = getbigcities(); 
    $distance = 1000000000; 
    $result = ''; 
    foreach ($bigcities as $bigcity) 
    { 

     $delta = $userinput->getDistanceInMetersTo(new POI($bigcity->lat,$bigcity->long)); 
     if($delta<$distance) 
     { 
      $result = $bigcity->name; 
      $distance = $delta; 
     } 
    } 

    return ($result); 
} 

echo findcity(51.556,5.091); //tilburg 
echo findcity(52.55,6.15); //leeuwaarden 
echo findcity(52.091,5.122); //utrecht 
exit; 
+0

感謝您的回答,對列表進行硬編碼不是一種選擇,我必須找到全球所有主要城市。我在爪哇做了一個刮板,它把所有的主要城市和他們的座標一起颳去了一些網站。你的例子非常有用,謝謝! – Jef 2013-05-07 22:52:12

0

對於那些有同樣的問題所困擾,我做了這擦傷大洲,國家,城市,緯度和經度從網站座標一些Java代碼。該代碼是不漂亮,因爲我在趕做,但它做什麼它應該做的事:

public class Main { 

private static String title; 
private static String land; 
private static Document docu; 
private static String continent = "Africa"; 

public static void main(String[] args) throws IOException { 
    String url = "http://www.timegenie.com/latitude_and_longitude/"; 

    Document doc = Jsoup.connect(url).get(); 
    Elements links = doc.select("a[href]"); 

    //print("\nLinks: (%d)", links.size()); 
    for (Element link : links) { 
     if (link.attr("abs:href").contains("country_coordinates")) { 
      try { 
       docu = Jsoup.connect(link.attr("abs:href")).get(); 
       title = docu.title(); 
       land = (trim(link.text(), 50)); 

       if (land.equals("Algeria")) { 
        continent = "Africa"; 
       } else if (land.equals("Antarctica")) { 
        continent = "Antarctica"; 
       } else if (land.equals("Afghanistan")) { 
        continent = "Asia"; 
       } else if (land.equals("Bouvet Island")) { 
        continent = "Antartica"; 
       } else if (land.equals("Anguilla")) { 
        continent = "North America"; 
       } else if (land.equals("Belize")) { 
        continent = "North America"; 
       } else if (land.equals("Armenia")) { 
        continent = "Asia"; 
       } else if (land.equals("Åland Islands") || land.equals("Aland Islands")) { 
        continent = "Europe"; 
       } else if (land.equals("Bassas da India")) { 
        continent = "Africa"; 
       } else if (land.equals("Akrotiri")) { 
        continent = "Asia"; 
       } else if (land.equals("Bermuda")) { 
        continent = "North America"; 
       } else if (land.equals("Clipperton Island")) { 
        continent = "North America"; 
       } else if (land.equals("Argentina")) { 
        continent = "South America"; 
       } else if (land.equals("American Samoa")) { 
        continent = "Oceania"; 
       } 

       Element table = docu.select("table.times").get(0); 
       Elements trs = table.select("tr"); 
       Iterator trIter = trs.iterator(); 
       boolean firstRow = true; 
       while (trIter.hasNext()) { 

        Element tr = (Element) trIter.next(); 
        if (firstRow) { 
         firstRow = false; 
         continue; 
        } 
        Elements tds = tr.select("td"); 
        Iterator tdIter = tds.iterator(); 
        int tdCount = 1; 
        String city = null; 
        String longgr = null; 
        String latgr= null; 

        while (tdIter.hasNext()) { 

         Element td = (Element) tdIter.next(); 
         switch (tdCount++) { 
          case 1: 
           city = td.select("a").text(); 
           break; 
          case 4: 
           latgr= td.text(); 
           break; 
          case 6: 
           longgr = td.text(); 
           break; 
         } 
        } 

        System.out.println(continent + "|" + land + "|" + city + "|" + latgr+ "|" + longgr+ "|"); 
       } 
      } catch (Exception ex) { 
       Elements links2 = docu.select("a[href]"); 

       for (Element link2 : links2) { 
        if (link2.attr("abs:href").contains("state_coordinates")) { 
         try { 
          try { 
           docu = Jsoup.connect(link2.attr("abs:href")).get(); 
           title = docu.title(); 

           Element table = docu.select("table.times").get(0); 
           Elements trs = table.select("tr"); 
           Iterator trIter = trs.iterator(); 
           boolean firstRow = true; 
           while (trIter.hasNext()) { 

            Element tr = (Element) trIter.next(); 
            if (firstRow) { 
             firstRow = false; 
             continue; 
            } 
            Elements tds = tr.select("td"); 
            Iterator tdIter = tds.iterator(); 
            int tdCount = 1; 
            String city = null; 
            String longgr = null; 
            String latgr= null; 


            while (tdIter.hasNext()) { 

             Element td = (Element) tdIter.next(); 
             switch (tdCount++) { 
              case 1: 
               city = td.select("a").text(); 
               break; 
              case 4: 
               latgr= td.text(); 
               break; 
              case 6: 
               longgr= td.text(); 
               break; 
             } 
            } 

            System.out.println(continent + "|" + land + "|" + city + "|" + latgr+ "|" + longgr+ "|"); 
           } 
          } catch (Exception e) { 
           e.printStackTrace(); 
          } 
         } catch (Exception x) { 
          x.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 
    } 
} 

private static void print(String msg, Object... args) { 
    System.out.println(String.format(msg, args)); 
} 

private static String trim(String s, int width) { 
    if (s.length() > width) { 
     return s.substring(0, width - 1) + "."; 
    } else { 
     return s; 
    } 
} 
} 

我用過的Jsoup庫。

這將需要一段時間(約3分鐘),運行這段代碼,它會返回大量的行(字貼:146頁)的格式,如:continent|country|city|lat|long|所以它會很容易將它們插入到數據庫中。

Cheers