【问题标题】:Listing geo-places near a user location列出用户位置附近的地理位置
【发布时间】:2011-06-14 01:00:05
【问题描述】:

我有一个 php webapp,它允许人们通过谷歌地图 api (v3) 插入他们的位置。然后我将 lat/lng 坐标存储到我的数据库中。

我做的另一件事是允许人们将某些事件添加到数据库中,然后我将事件插入到我的数据库中,并使用与用户相同的 lat/lng。例如:

用户表:

ID    U_Name    U_Location_ID
1     test      23

事件表:

ID    E_Name    E_Location_ID
1     testevent 23

位置表:

ID    L_LAT        L_LNG        L_Name
23    40.759139    -73.979723   30 Rockefeller Plaza, New York, NY 10112, USA

我现在要做的是向用户显示他所在位置附近的事件列表。

我不一定知道他的确切位置,但通常只有国家和城市(并非所有访问者都是填写确切位置的注册会员)。

所以当一个成员访问时,我使用一个 ip 来定位 api,它给了我他的国家名称和城市名称。我有另一种获取国家/城市纬度/经度坐标的方法,但现在当我需要显示该城市/国家的附近事件时,我被卡住了。

当我说“接近”时,我希望可以以公里或英里为单位设置某种直径并列出该直径内的事件。

感谢您的帮助

【问题讨论】:

    标签: php mysql google-maps geolocation


    【解决方案1】:

    这里是 MySQL 中适用于每个表的完整查询。请记住,纬度/经度字段必须是十进制字段,除非您会降低精度:

    -- set your vars
    SET @lat := $$$$$;
    SET @lon := $$$$$;
    SET @dist := $$$$$;
    
    -- prepare a square in miles
    SET @x1 := @lon - @dist / ABS(COS(RADIANS(@lat))*69);
    SET @x2 := @lon + @dist / ABS(COS(RADIANS(@lat))*69);
    SET @y1 := @lat - (@dist / 69);
    SET @y2 := @lat + (@dist / 69);
    
    SELECT  t.*, 
            3956 * 2 * ASIN(
                SQRT(
                    POWER(
                        SIN(
                            (@lat - t.lat) * pi() / 180 / 2
                        ), 2
                    ) +
                    COS(
                        @lat * pi() / 180
                    ) *
                    COS(
                        t.lat * pi() / 180
                    ) *
                    POWER(
                        SIN(
                            (@lon - t.lon) * pi() / 180 / 2
                        ), 2
                    )
                )
            ) as distance
    FROM    `YourTable` t
    WHERE   t.longitude BETWEEN @x1 AND @x2
    AND     t.latitude BETWEEN @y1 AND @y2
    HAVING  distance < @dist
    ORDER BY distance
    LIMIT 10;
    

    您只需将$$$$$ 替换为您的值。 现在,如果您想要完整的解释,请参阅slides by Alexander Rubin

    对于公里,只需将 x1x2 ... 替换为

    -- prepare a square or in kilometers
    SET @x1 := @lon - @dist / ABS(COS(RADIANS(@lat))*110);
    SET @x2 := @lon + @dist / ABS(COS(RADIANS(@lat))*110);
    SET @y1 := @lat - (@dist / 110);
    SET @y2 := @lat + (@dist / 110);
    

    【讨论】:

    • @dist 是如何定义的?公里?
    • 当前以英里为单位。我已经更新了我的帖子以显示如何在公里内请求。
    • 当我尝试通过 mysql_query() 运行此查询时出现错误,您知道原因吗?
    • 每个; 尝试一个查询,像这样:mysql_query('SET @lat := $$$$$'); mysql_query('SET @ lon := $$$$$'); ...
    • @XavierBarbosa 你能看看布里顿的评论吗,谢谢你的精彩回答
    【解决方案2】:

    重要的是要注意,如果您选择 Xavier 的精彩答案-并且--如果您使用他的公里数变化,您还必须在计算中将 3956 * 2 更改为 6371 * 2 ,否则您只是在更改范围,而不是产生的距离。

    【讨论】:

      【解决方案3】:

      我不是很理解你的问题。如果您使用 MaxMind 之类的地理定位数据库,您还可以到达每个城市的纬度/经度。您只需为经度和纬度选择一些增量,运行 SQL 查询并在您的视图中计算从用户位置到事件位置的距离。这并不复杂。

      【讨论】:

      • LAT/LNG 的正确计算方法是什么?如果这是我的 LAT/LNG:40.759139/-73.979723,并且我想从 mysql DB 中选择距离该 LAT/LNG 50KM 范围内的所有事件,我该如何执行?
      【解决方案4】:

      你知道mysql spatial extensions吗?

      【讨论】:

        【解决方案5】:

        这是一个查询,它可以帮助您获取特定直径内的所有位置。 {NUMBER OF KILOMETERS} 将是直径。 $lon AND $lat 将赌用户位置的坐标。

        SELECT D.*, DEGREES(acos(cos(RADIANS(90-latitude))*cos(RADIANS(90-$lat))+sin(RADIANS(90-latitude))*sin(RADIANS(90-$lat))*cos(RADIANS(longitude-$lon))))/360*40074 AS distance FROM location_table as D HAVING distance <= {NUMBER OF KILOMETERS}

        【讨论】:

          猜你喜欢
          • 2016-05-08
          • 2020-11-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-20
          • 2023-03-28
          • 2011-06-09
          • 1970-01-01
          相关资源
          最近更新 更多