0

我有一个简单的 php 函数,它可以从给定的纬度和经度获取最近的附近城市:

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>";
    } 

此方法返回以下内容,lat:51.992 和 long: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
                )

        )

)

这将返回最近的城市,但我正在寻找这样的东西。只返回最近的大城市。这可能吗?或者是否有其他方法可以解决这个问题。我已经阅读了有关 Google Geocoding API 的信息,但我们不能使用它,因为我们没有使用 Google 地图来显示结果。(注意:Geocoding API 只能与谷歌地图一起使用;禁止在地图上不显示的地理编码结果。 来源

我知道这不是一个真正的程序员问题,但由于 geonames 论坛并不活跃,我想我会在这里发布。

4

2 回答 2

1

你需要一个最大城市的列表。我没有找到关于地理名称的 api 调用(也许可以尝试使用 freebase api 来按城市相关性进行排序)。因为您显示的示例列表很短,您可以对其进行硬编码吗?如果是这样,您可以使用如下所示的内容:

/*
* 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;
于 2013-04-23T22:21:39.390 回答
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 分钟),它会返回很多行(用 word 粘贴:146 页),格式如下:continent|country|city|lat|long|所以很容易将它们插入数据库。

干杯

于 2013-05-07T23:03:43.193 回答