mysql 圆心距离_MySQL大圆距离(Haversine公式)

80a635a7761ce120f97ac559177bdeb5.png

春华秋衣

如果将助手字段添加到坐标表中,则可以提高查询的响应时间。就像这样:CREATE TABLE `Coordinates` (`id` INT(10) UNSIGNED NOT NULL COMMENT 'id for the object',`type` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'type',`sin_lat` FLOAT NOT NULL COMMENT 'sin(lat) in radians',`cos_cos` FLOAT NOT NULL COMMENT 'cos(lat)*cos(lon) in radians',`cos_sin` FLOAT NOT NULL COMMENT 'cos(lat)*sin(lon) in radians',`lat` FLOAT NOT NULL COMMENT 'latitude in degrees',`lon` FLOAT NOT NULL COMMENT 'longitude in degrees',INDEX `lat_lon_idx` (`lat`, `lon`))    如果您正在使用TokuDB,那么如果在任何一个谓词上添加集群索引,您将获得更好的性能,例如:alter table Coordinates add clustering index c_lat(lat);alter table Coordinates add clustering index c_lon(lon);每个点都需要基本的LAT和LON,弧度中的sin(LAT),弧度中的cos(LAT)*cos(Lon),弧度的cos(LAT)*罪恶(LON)。然后创建一个MySQL函数,smth如下所示:CREATE FUNCTION `geodistance`(`sin_lat1` FLOAT,                              `cos_cos1` FLOAT, `cos_sin1` FLOAT,                              `sin_lat2` FLOAT,                              `cos_cos2` FLOAT, `cos_sin2` FLOAT)    RETURNS float    LANGUAGE SQL    DETERMINISTIC    CONTAINS SQL    SQL SECURITY INVOKER   BEGIN   RETURN acos(sin_lat1*sin_lat2 + cos_cos1*cos_cos2 + cos_sin1*cos_sin2);   END这给了你距离。不要忘记在LAT/lon上添加索引,这样边界装箱可以帮助搜索而不是减慢搜索速度(索引已经添加到上面的CREATETABLE查询中)。INDEX `lat_lon_idx` (`lat`, `lon`)给定一个只有lat/lon坐标的旧表,您可以设置一个脚本来像这样更新它:(PHP使用meekrodb)$users = DB::query('SELECT id,lat,lon FROM Old_Coordinates');foreach ($users as $user){  $lat_rad = deg2rad($user['lat']);  $lon_rad = deg2rad($user['lon']);  DB::replace('Coordinates', array(    'object_id' => $user['id'],    'object_type' => 0,    'sin_lat' => sin($lat_rad),    'cos_cos' => cos($lat_rad)*cos($lon_rad),    'cos_sin' => cos($lat_rad)*sin($lon_rad),    'lat' => $user['lat'],    'lon' => $user['lon']  ));}然后优化实际查询,只在真正需要时进行距离计算,例如,从内部和外部包围圆圈(嗯,椭圆)。为此,您需要为查询本身预先计算几个指标:// assuming the search center coordinates are $lat and $lon in degrees// and radius in km is given in $distance$lat_rad = deg2rad($lat);$lon_rad = deg2rad($lon);$R = 6371; // earth's radius, km$distance_rad = $distance/$R;$distance_rad_plus = $distance_rad * 1.06; // ovality error for outer bounding box$dist_deg_lat = rad2deg($distance_rad_plus); //outer bounding box$dist_deg_lon = rad2deg($distance_rad_plus/cos(deg2rad($lat)));$dist_deg_lat_small = rad2deg($distance_rad/sqrt(2)); //inner bounding box$dist_deg_lon_small = rad2deg($distance_rad/cos(deg2rad($lat))/sqrt(2));考虑到这些准备工作,查询如下(Php):$neighbors = DB::query("SELECT id, type, lat, lon,       geodistance(sin_lat,cos_cos,cos_sin,%d,%d,%d) as distance       FROM Coordinates WHERE       lat BETWEEN %d AND %d AND lon BETWEEN %d AND %d       HAVING (lat BETWEEN %d AND %d AND lon BETWEEN %d AND %d) OR distance <= %d",  // center radian values: sin_lat, cos_cos, cos_sin       sin($lat_rad),cos($lat_rad)*cos($lon_rad),cos($lat_rad)*sin($lon_rad),  // min_lat, max_lat, min_lon, max_lon for the outside box       $lat-$dist_deg_lat,$lat+$dist_deg_lat,       $lon-$dist_deg_lon,$lon+$dist_deg_lon,  // min_lat, max_lat, min_lon, max_lon for the inside box       $lat-$dist_deg_lat_small,$lat+$dist_deg_lat_small,       $lon-$dist_deg_lon_small,$lon+$dist_deg_lon_small,  // distance in radians       $distance_rad);对上述查询的解释可能会说,除非有足够的结果触发索引,否则它不会使用索引。当坐标表中有足够的数据时,将使用索引。可以向SELECT中添加强制索引(LAT_LON_IDX),使其使用索引而不考虑表大小,因此可以使用EXPLAIN验证它是否正确工作。有了上面的代码示例,您应该有一个工作的、可伸缩的对象搜索实现,且错误最小。

### 回答1: Haversine距离公式是一种计算地球表面两点间距离的方法,其基本思想是将地球看作是一个球体,通过计算两点间的球面距离来表示它们之间的距离公式如下: d = 2r * arcsin(sqrt(sin^2((lat2-lat1)/2) + cos(lat1) * cos(lat2) * sin^2((lon2-lon1)/2))) 其中,d表示两点间的距离(单位为地球半径r),lat1和lat2表示两点的纬度,lon1和lon2表示两点的经度。 ### 回答2: Haversine距离公式是计算两个经纬度坐标点之间最短曲线距离的一种方法。它基于球形大地模型,假设地球是一个完美的球体。 该公式使用了三角函数来确定两个点之间的弧度距离。首先,我们需要将经纬度坐标转换为弧度值,然后使用Haversine函数计算两个点之间的弧度距离。 Haversine函数的数学表达式如下: haversin(θ) = sin²(θ/2) 其中,θ是两个点之间的弧度距离,可以通过以下公式计算: a = sin²((lat2 - lat1)/2) + cos(lat1) * cos(lat2) * sin²((lon2 - lon1)/2) c = 2 * atan2(√a, √(1-a)) d = R * c 其中,lat1和lon1是第一个点的纬度和经度,lat2和lon2是第二个点的纬度和经度。R是地球的半径,通常取6371千米。 计算出的d即为两个点之间的弧度距离,它表示的是地球表面上的最短曲线距离。 Haversine距离公式在地图应用程序中广泛使用,特别是在计算两个地理位置之间的距离时非常便捷。由于其简单性和准确性,它被视为一种常用的距离计算方法。 ### 回答3: Haversine距离公式是一种用于计算两个经纬度坐标之间距离的数学公式。它基于大圆距离的概念,通过考虑地球球面的曲率来计算两点之间的最短路径距离。 Haversine距离公式的基本形式如下: d = 2r * arcsin(sqrt(sin^2((lat2 - lat1)/2) + cos(lat1) * cos(lat2) * sin^2((lon2 - lon1)/2))) 其中,d表示两点之间的距离,r表示地球半径,单位可以是千米、英里或其他长度单位。lat1和lon1表示第一个点的纬度和经度,lat2和lon2表示第二个点的纬度和经度。上述公式中的单位是弧度,所以需要对纬度和经度进行弧度转换。 具体来说,公式首先计算了两点纬度差和经度差的sin的平方,然后使用三角函数和开方运算,得到两个sin的平方的和。然后将该和带入arcsin函数,再乘以2倍的地球半径r,即可得到两点之间的距离d。 Haversine距离公式在地理信息系统(GIS)和航海导航中经常被用于计算两个经纬度坐标之间的距离。它提供了一种较为准确的近似方法,可以在不考虑地球形状的情况下,对两个点之间的直线距离进行估算。然而,需要注意的是,Haversine距离公式没有考虑地球椭球体的形状、地球多极不规则性、以及海拔高度的差异等因素。所以在具体应用中,可能需要结合其他因素进行修正,以得到更准确的距离计算结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值