<div class="show-content-free"> <h3>根据经纬度计算距离公式</h3> <div class="image-view" data-width="437" data-height="76"><img data-original-src="//upload-images.jianshu.io/upload_images/2833665-36cf75cbabf61869.png" data-original-width="437" data-original-height="76" data-original-format="image/png" data-original-filesize="14687" class="" style="cursor: zoom-in;" src="//upload-images.jianshu.io/upload_images/2833665-36cf75cbabf61869.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/437/format/webp"></div> <div class="image-caption">公式</div> <p>对上面的公式解释以下:</p> <ol> <li>Lung1 Lat1表示A点经纬度, Lung2 Lat2表示B点经纬度;</li> <li>a=Lat1 – Lat2 为两点纬度之差 b=Lung1 -Lung2 为两点经度之差;</li> <li>6378.137为地球半径,单位为公里;</li> <li>计算出来的结果单位为公里,若将半径改成米为单位则计算的结果单位为米。</li> <li>计算精度与谷歌地图的距离精度差很少,相差范围在0.2米如下。</li> </ol> <h3>参数说明</h3> <p>lng:经度<br> lat:纬度<br> 地球半径:6378.137(公里)</p> <p>通常地图上显示的坐标顺序为,纬度在前(范围-90 ~ 90),经度在后(范围-180 ~ 180)</p> <h3>各类语言计算距离的代码</h3> <blockquote> <p>这种计算方式通常都是直线距离</p> </blockquote> <p>sql语句</p> <pre class="hljs php"><code class="php">SELECT *, <span class="hljs-number">6378.138</span> * <span class="hljs-number">2</span> * ASIN( SQRT( POW( SIN( ( <span class="hljs-string">'.$lat.'</span> * PI() / <span class="hljs-number">180</span> - lat * PI() / <span class="hljs-number">180</span> ) / <span class="hljs-number">2</span> ), <span class="hljs-number">2</span> ) + COS(<span class="hljs-string">'.$lat.'</span> * PI() / <span class="hljs-number">180</span>) * COS(lat * PI() / <span class="hljs-number">180</span>) * POW( SIN( ( <span class="hljs-string">'.$lng.'</span> * PI() / <span class="hljs-number">180</span> - lng * PI() / <span class="hljs-number">180</span> ) / <span class="hljs-number">2</span> ), <span class="hljs-number">2</span> ) ) ) *<span class="hljs-number">1000</span> <span class="hljs-keyword">AS</span> distance FROM distance ORDER BY distance ASC </code></pre> <p>php计算距离</p> <pre class="hljs php"><code class="php"><span class="hljs-comment">/** * 根据两点间的经纬度计算距离 * <span class="hljs-doctag">@param</span> $lng1 * <span class="hljs-doctag">@param</span> $lat1 * <span class="hljs-doctag">@param</span> $lng2 * <span class="hljs-doctag">@param</span> $lat2 * <span class="hljs-doctag">@return</span> int */</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getDistance</span><span class="hljs-params">($lng1, $lat1, $lng2, $lat2)</span> </span>{ <span class="hljs-comment">//将角度转为狐度</span> $radLat1 = deg2rad($lat1);<span class="hljs-comment">//deg2rad()函数将角度转换为弧度</span> $radLat2 = deg2rad($lat2); $radLng1 = deg2rad($lng1); $radLng2 = deg2rad($lng2); $a = $radLat1 - $radLat2; $b = $radLng1 - $radLng2; $s = <span class="hljs-number">2</span> * asin(sqrt(pow(sin($a / <span class="hljs-number">2</span>), <span class="hljs-number">2</span>) + cos($radLat1) * cos($radLat2) * pow(sin($b / <span class="hljs-number">2</span>), <span class="hljs-number">2</span>))) * <span class="hljs-number">6378.137</span> * <span class="hljs-number">1000</span>; <span class="hljs-keyword">return</span> $s; } </code></pre> <p>js求距离的方法</p> <pre class="hljs javascript"><code class="javascript"><span class="hljs-comment">/** * 转换弧度 * @param d * @returns {number} */</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRad</span>(<span class="hljs-params">d</span>)</span>{ <span class="hljs-keyword">var</span> PI = <span class="hljs-built_in">Math</span>.PI; <span class="hljs-keyword">return</span> d*PI/<span class="hljs-number">180.0</span>; }javascript
<span class="hljs-comment">/**php
- 根据经纬度计算两点间距离
- @param lng1
- @param lat1
- @param lng2
- @param lat2
- @returns {number|*}
- @constructor /</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CoolWPDistance</span>(<span class="hljs-params">lng1,lat1,lng2,lat2</span>)</span>{ <span class="hljs-keyword">var</span> f = getRad((lat1 + lat2)/<span class="hljs-number">2</span>); <span class="hljs-keyword">var</span> g = getRad((lat1 - lat2)/<span class="hljs-number">2</span>); <span class="hljs-keyword">var</span> l = getRad((lng1 - lng2)/<span class="hljs-number">2</span>); <span class="hljs-keyword">var</span> sg = <span class="hljs-built_in">Math</span>.sin(g); <span class="hljs-keyword">var</span> sl = <span class="hljs-built_in">Math</span>.sin(l); <span class="hljs-keyword">var</span> sf = <span class="hljs-built_in">Math</span>.sin(f); <span class="hljs-keyword">var</span> s,c,w,r,d,h1,h2; <span class="hljs-keyword">var</span> a = <span class="hljs-number">6378137.0</span>;<span class="hljs-comment">//The Radius of eath in meter.</span> <span class="hljs-keyword">var</span> fl = <span class="hljs-number">1</span>/<span class="hljs-number">298.257</span>; sg = sgsg; sl = slsl; sf = sfsf; s = sg*(<span class="hljs-number">1</span>-sl) + (<span class="hljs-number">1</span>-sf)sl; c = (<span class="hljs-number">1</span>-sg)(<span class="hljs-number">1</span>-sl) + sfsl; w = <span class="hljs-built_in">Math</span>.atan(<span class="hljs-built_in">Math</span>.sqrt(s/c)); r = <span class="hljs-built_in">Math</span>.sqrt(sc)/w; d = <span class="hljs-number">2</span>wa; h1 = (<span class="hljs-number">3</span>r <span class="hljs-number">-1</span>)/<span class="hljs-number">2</span>/c; h2 = (<span class="hljs-number">3</span>r +<span class="hljs-number">1</span>)/<span class="hljs-number">2</span>/s; s = d(<span class="hljs-number">1</span> + fl(h1sf(<span class="hljs-number">1</span>-sg) - h2*(<span class="hljs-number">1</span>-sf)*sg)); <span class="hljs-keyword">if</span>(s >= <span class="hljs-number">1000</span> && s <= <span class="hljs-number">99000</span>){ <span class="hljs-keyword">var</span> kilometer = s/<span class="hljs-number">1000</span>; s = kilometer.toFixed(<span class="hljs-number">1</span>) + <span class="hljs-string">'km'</span>; }<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(s > <span class="hljs-number">99000</span>){ s = <span class="hljs-string">'>99km'</span>; }<span class="hljs-keyword">else</span>{ s = <span class="hljs-built_in">Math</span>.round(s) + <span class="hljs-string">'m'</span>; } <span class="hljs-comment">// s = s/1000;</span> <span class="hljs-comment">// s = s.toFixed(2);//指定小数点后的位数。</span> <span class="hljs-keyword">return</span> s; }
</code></pre>java
<p>以上代码大部分来自网上收集,通过验证过的,可使用</p> <h1>原理</h1> <p>根据两点经纬度计算距离</p> <p>这些经纬线是怎样定出来的呢?地球是在不停地绕地轴旋转(地轴是一根经过地球南北两极和地球中心的假想线),在地球中腰画一个与地轴垂直的大圆圈,使圈上的每一点都和南北两极的距离相等,这个圆圈就叫做“赤道”。</p> <p>在赤道的南北两边,画出许多和赤道平行的圆圈,就是“纬圈”;构成这些圆圈的线段,叫作纬线。咱们把赤道定为纬度零度,向南向北各为90度,在赤道以南的叫南纬,在赤道以北的叫北纬。北极就是北纬90度,南极就是南纬90度。纬度的高低也标志着气候的冷热,如赤道和低纬度地地区无冬,两极和高纬度地区无夏,中纬度地区四季分明。 其次,从北极点到南极点,能够画出许多南北方向的与地球赤道垂直的大圆圈,这叫做“经圈”;构成这些圆圈的线段,就叫经线。</p> <p>公元1884平面坐标图年,国际上规定以经过英国伦敦近郊的格林尼治天文台的经线做为计算经度的起点,即经度零度零分零秒,也称“本初子午线”。在它东面的为东经,共180度;在它西面的为西经,共180度。由于地球是圆的,因此东经180度和西经180度的经线是同一条经线。各国公定180度经线为“国际日期变动线”。</p> <p>为了不同一地区使用两个不一样的日期,国际日期变线在遇陆地时略有偏离。 每一经度和纬度还能够再细分为60分,每一分再分为60秒以及秒的小数。利用经纬线,咱们就能够肯定地球上每个地方的具体位置,而且把它在地图或地球仪上表示出来。</p> <p>例如问北京的经纬度是多少?咱们很容易从地图上查出来是东经116度24分,北纬39度54分。在大海中航行的船只,只要把所在地的经度测出来,就能够肯定船在海洋中的位置和前进方向。 纬度共有90度。赤道为0度,向两极排列,圈子越小,度数越大。横线是纬度,竖线是经度。<br> 固然能够计算,四元二次方程。 经度和纬度都是一种角度。经度是个两面角,是两个经线平面的夹角。因全部经线都是同样长,为了度量经度选取一个起点面,经1884年国际会议协商,决定以经过英国伦敦近郊、泰晤士河南岸的格林尼治皇家天文台(旧址)的一台主要子午仪十字丝的那条经线为起始经线,称为本初子午线。</p> <p>本初子午线平面是起点面,终点面是本地经线平面。某一点的经度,就是该点所在的经线平面与本初子午线平面间的夹角。在赤道上度量,自本初子午线平面做为起点面,分别往东往西度量,往东量值称为东经度,往西量值称为西<br> 经度。因而可知,一地的经度是该地对于本初子午线的方向和角距离。本初子午线是0°经度,东经度的最大值为180°,西经度的最大值为180°,东、西经180°经线是同一根经线,所以不分东经或西经,而统称180°经线。 纬度是个线面角。起点面是赤道平面,线是本地的地面法线。所谓法线,即垂直于参考扁球体表面的线。某地的纬度就是该地的法线与赤道平面之间的夹角。纬度在本地经线上度量,由赤道向南、北度量,向北量值称为北纬度,向南量值称为南纬度。因而可知,一地的纬度是该地对于赤道的方向和角距离。赤道是0°纬线,北纬度的最大值为90°,即北极点;南纬度的最大值为90°,即南极点。</p> <h1>经纬度互换</h1> <p>度(DDD):E 108.90593度 N 34.21630度</p> <p>如何将度(DDD): 108.90593度换算成度分秒(DMS)东经E 108度54分22.2秒?<br> 转换方法是将108.90593整数位不变取108(度),用0.90593<em>60=54.3558,取整数位54(分),0.3558</em>60=21.348再取整数位21(秒),故转化为108度54分21秒.</p> <p>一样将度分秒(DMS):东经E 108度54分22.2秒 换算成度(DDD)的方法以下:108度54分22.2秒=108+(54/60)+(22.2/3600)=108.90616度</p> <p>由于计算时小数位保留的缘由,致使正反计算存在必定偏差,但偏差影响不是很大。1秒的偏差就是几米的样子。GPS车友能够用上述方法换算成本身须要的单位坐标。</p> <h1>经纬度换算成米</h1> <p>纬度分为60分,每一分再分为60秒以及秒的小数。</p> <p>纬度线投射在图上看似水平的平行线,但其实是不一样半径的圆。有相同特定纬度的全部位置都在同一个纬线上。<br> 赤道的纬度为0°,将行星平分为南半球和北半球。<br> 纬度是指某点与地球球心的连线和地球赤道面所成的线面角,其数值在0至90度之间。位于赤道以北的点的纬度叫北纬,记为N,位于赤道以南的点的纬度称南纬,记为S。<br> 纬度数值在0至30度之间的地区称为低纬地区,纬度数值在30至60度之间的地区称为中纬地区,纬度数值在60至90度之间的地区称为高纬地区。<br> 赤道、南回归线、北回归线、南极圈和北极圈是特殊的纬线。<br> 纬度1秒的长度<br> 地球的子午线总长度大约40008km。平均:<br> 纬度1度 = 大约111km<br> 纬度1分 = 大约1.85km<br> 纬度1秒 = 大约30.9m</p> <p>根据地球上任意两点的经纬度计算两点间的距离</p> <p>地球是一个近乎标准的椭球体,它的赤道半径为6378.140公里,极半径为 6356.755公里,平均半径6371.004公里。若是咱们假设地球是一个完美的球体,那么它的半径就是地球的平均半径,记为R。若是以0度经线为基 准,那么根据地球表面任意两点的经纬度就能够计算出这两点间的地表距离(这里忽略地球表面地形对计算带来的偏差,仅仅是理论上的估算值)。设第一点A的经 纬度为(LonA, LatA),第二点B的经纬度为(LonB, LatB),按照0度经线的基准,东经取经度的正值(Longitude),西经取经度负值(-Longitude),北纬取90-纬度值(90- Latitude),南纬取90+纬度值(90+Latitude),则通过上述处理事后的两点被计为(MLonA, MLatA)和(MLonB, MLatB)。那么根据三角推导,能够获得计算两点距离的以下公式:</p> <pre class="hljs cpp"><code class="cpp">C = <span class="hljs-built_in">sin</span>(MLatA)*<span class="hljs-built_in">sin</span>(MLatB)*<span class="hljs-built_in">cos</span>(MLonA-MLonB) + <span class="hljs-built_in">cos</span>(MLatA)*<span class="hljs-built_in">cos</span>(MLatB) Distance = R*Arccos(C)*Pi/<span class="hljs-number">180</span> </code></pre> <p>这里,R和Distance单位是相同,若是是采用6371.004公里做为半径,那么Distance就是公里为单位,若是要使用其余单位,好比mile,还须要作单位换算,1公里=0.621371192mile</p> <p>若是仅对经度做正负的处理,而不对纬度做90-Latitude(假设都是北半球,南半球只有澳洲具备应用意义)的处理,那么公式将是:</p> <pre class="hljs cpp"><code class="cpp">C = <span class="hljs-built_in">sin</span>(LatA)*<span class="hljs-built_in">sin</span>(LatB) + <span class="hljs-built_in">cos</span>(LatA)*<span class="hljs-built_in">cos</span>(LatB)*<span class="hljs-built_in">cos</span>(MLonA-MLonB)git
Distance = R*Arccos(C)*Pi/<span class="hljs-number">180</span> </code></pre>web
<p>以上经过简单的三角变换就能够推出。</p> <p>若是三角函数的输入和输出都采用弧度值,那么公式还能够写做:</p> <pre class="hljs cpp"><code class="cpp">C = <span class="hljs-built_in">sin</span>(LatA*Pi/<span class="hljs-number">180</span>)*<span class="hljs-built_in">sin</span>(LatB*Pi/<span class="hljs-number">180</span>) + <span class="hljs-built_in">cos</span>(LatA*Pi/<span class="hljs-number">180</span>)*<span class="hljs-built_in">cos</span>(LatB*Pi/<span class="hljs-number">180</span>)*<span class="hljs-built_in">cos</span>((MLonA-MLonB)*Pi/<span class="hljs-number">180</span>)sql
Distance = R*Arccos(C)*Pi/<span class="hljs-number">180</span> </code></pre>数据库
<p>也就是:</p> <pre class="hljs cpp"><code class="cpp">C = <span class="hljs-built_in">sin</span>(LatA/<span class="hljs-number">57.2958</span>)*<span class="hljs-built_in">sin</span>(LatB/<span class="hljs-number">57.2958</span>) + <span class="hljs-built_in">cos</span>(LatA/<span class="hljs-number">57.2958</span>)*<span class="hljs-built_in">cos</span>(LatB/<span class="hljs-number">57.2958</span>)*<span class="hljs-built_in">cos</span>((MLonA-MLonB)/<span class="hljs-number">57.2958</span>)函数
Distance = R*Arccos(C) = <span class="hljs-number">6371.004</span>Arccos(C) kilometer = <span class="hljs-number">0.621371192</span><span class="hljs-number">6371.004</span>*Arccos(C) mile = <span class="hljs-number">3958.758349716768</span>*Arccos(C) mile </code></pre>ui
<p>在实际应用当中,通常是经过一个个体的邮政编码来查找该邮政编码对应的地区中心的经纬度,然 后再根据这些经纬度来计算彼此的距离,从而估算出某些群体之间的大体距离范围(好比酒店旅客的分布范围-各个旅客的邮政编码对应的经纬度和酒店的经纬度所 计算的距离范围-等等),因此,经过邮政编码查询经纬度这样一个数据库是一个颇有用的资源。</p>编码
</div>