【问题标题】:get nearby from mysql database with latitude and longitude从具有纬度和经度的mysql数据库获取附近
【发布时间】:2015-03-04 20:31:23
【问题描述】:

我有一个包含多个事件的事件数据库,每个事件都有不同的纬度和经度,如果我当前的纬度是 30.7263962,经度是 76.7664144,我如何从数据库中获取距离我所在位置不到 100 公里的事件?谁能建议我查询?谢谢

【问题讨论】:

  • 你需要正弦公式
  • 出于性能原因,您可以先使用 delta latitude 和 delta longitude 进行不准确的查询,然后使用 hasrsine 公式检查找到的事件。在 gis.stackexchange 中查看 answer

标签: php codeigniter maps


【解决方案1】:

一些示例代码您可以随意使用(我已尝试适应您的需求,但做出了一些疯狂的猜测)。
这是haversine算法的一个版本,使用Rhumb线(或loxodrome)

<?php
function search($device_latitude, $device_longitude, $radius, $radius_type)
{
    $events = array();

    $sql = "SELECT `event_id`, `last_updated`, `location_lat`, `location_long` FROM `event`";
    $query = $this->db->query($sql);

    if ($query->num_rows() > 0)
    {
        foreach ($query->result() as $row)
        {
            $geo_data = $this->_bearing_distance_calc($device_latitude, $device_longitude, $row->location_lat, $row->location_long, $radius_type);
            $geo_data['radius_type'] = $radius_type;
            // $geo_data contains => 'distance', 'bearing'
            if($geo_data['distance'] <= $radius)
            {
                $events[] = $this->event->load($row->event_id);
            }
        }
        return $events;
    }
    $this->error_msg = "Search failed.";
    return NULL;
}

function _bearing_distance_calc($device_latitude, $device_longitude, $event_latitude, $event_longitude, $radius_type)
{
    // using Rhumb lines(or loxodrome)
    // convert to rads for php trig functions
    $device_latitude = deg2rad($device_latitude);
    $device_longitude = deg2rad($device_longitude);
    $event_latitude = deg2rad($event_latitude);
    $event_longitude = deg2rad($event_longitude);

    // calculate delta of lat and long
    $delta_latitude = $event_latitude-$device_latitude;
    $delta_longitude = $event_longitude-$device_longitude;

    // earth radius
    if ($radius_type == 'Miles')
    {
        $earth_radius = 3959;
    }
    else
    {
        $earth_radius = 6371;
    }

    // now lets start mathing !!
    $dPhi = log(tan($event_latitude/2+M_PI/4)/tan($device_latitude/2+M_PI/4));
    if ($dPhi != 0)
    {
        $q = $delta_latitude/$dPhi;
    }
    else
    {
        $q = cos($device_latitude);
    }
    //$q = (!is_nan($delta_latitude/$dPhi)) ? $delta_latitude/$dPhi : cos($device_latitude);  // E-W line gives dPhi=0

    // if dLon over 180° take shorter rhumb across 180° meridian:
    if (abs($delta_longitude) > M_PI)
    {
        $delta_longitude = $delta_longitude>0 ? -(2*M_PI-$delta_longitude) : (2*M_PI+$delta_longitude);
    }

    $geo_data = array();
    $geo_data['distance'] = sqrt($delta_latitude*$delta_latitude + $q*$q*$delta_longitude*$delta_longitude) * $earth_radius;
    $bearing = rad2deg(atan2($delta_longitude, $dPhi));

    if($bearing < 0)
    {
        $bearing = 360 + $bearing;
    }
    $geo_data['bearing'] = $bearing;

    return $geo_data;
}

【讨论】:

    【解决方案2】:

    您需要将距离转换为经度和纬度,根据这些过滤以限制大致在边界框中的条目,然后进行更精确的距离过滤。这是一篇很棒的论文,解释了如何做到这一点:

    http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-07
      • 2019-08-04
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 2021-10-10
      相关资源
      最近更新 更多