利用java、js或mysql計(jì)算高德地圖中兩坐標(biāo)之間的距離
前言
因?yàn)楣ぷ鞯脑?,最近在做與地圖相關(guān)的應(yīng)用,使用了高德地圖,研究了下高德地圖計(jì)算兩坐標(biāo)距離的方法,官網(wǎng)上提供的開發(fā)包中有相關(guān)的方法,但是我的產(chǎn)品中比較特殊,無(wú)法直接使用提供的方法,所以就自己封裝了相關(guān)計(jì)算方法,供大家參考,下面話不多說(shuō)了,來(lái)一起看看詳細(xì)的介紹吧。
Java實(shí)現(xiàn)
首先定義一個(gè)用于存儲(chǔ)經(jīng)緯度的類,這里起個(gè)名字叫:LngLat
package amap; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; /** * 存儲(chǔ)經(jīng)緯度坐標(biāo)值的類,單位角度 * * @author jianggujin * */ public final class LngLat implements Cloneable { /** * 緯度 (垂直方向) */ public final double latitude; /** * 經(jīng)度 (水平方向) */ public final double longitude; /** * 格式化 */ private static DecimalFormat format = new DecimalFormat("0.000000", new DecimalFormatSymbols(Locale.US)); /** * 使用傳入的經(jīng)緯度構(gòu)造LatLng 對(duì)象,一對(duì)經(jīng)緯度值代表地球上一個(gè)地點(diǎn)。 * * @param longitude * 地點(diǎn)的經(jīng)度,在-180 與180 之間的double 型數(shù)值。 * @param latitude * 地點(diǎn)的緯度,在-90 與90 之間的double 型數(shù)值。 */ public LngLat(double longitude, double latitude) { this(longitude, latitude, true); } /** * 使用傳入的經(jīng)緯度構(gòu)造LatLng 對(duì)象,一對(duì)經(jīng)緯度值代表地球上一個(gè)地點(diǎn) * * @param longitude * 地點(diǎn)的經(jīng)度,在-180 與180 之間的double 型數(shù)值。 * * @param latitude * 地點(diǎn)的緯度,在-90 與90 之間的double 型數(shù)值。 * @param isCheck * 是否需要檢查經(jīng)緯度的合理性,建議填寫true */ public LngLat(double longitude, double latitude, boolean isCheck) { if (isCheck) { if ((-180.0D <= longitude) && (longitude < 180.0D)) this.longitude = parse(longitude); else { throw new IllegalArgumentException("the longitude range [-180, 180]."); // this.longitude = parse(((longitude - 180.0D) % 360.0D + 360.0D) % // 360.0D - 180.0D); } if ((latitude < -90.0D) || (latitude > 90.0D)) { throw new IllegalArgumentException("the latitude range [-90, 90]."); } this.latitude = latitude; // this.latitude = parse(Math.max(-90.0D, Math.min(90.0D, latitude))); } else { this.latitude = latitude; this.longitude = longitude; } } /** * 解析 * * @param d * @return */ private static double parse(double d) { return Double.parseDouble(format.format(d)); } public LngLat clone() { return new LngLat(this.latitude, this.longitude); } @Override public int hashCode() { final int prime = 31; int result = 1; long temp; temp = Double.doubleToLongBits(latitude); result = prime * result + (int) (temp ^ (temp >>> 32)); temp = Double.doubleToLongBits(longitude); result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; LngLat other = (LngLat) obj; if (Double.doubleToLongBits(latitude) != Double.doubleToLongBits(other.latitude)) return false; if (Double.doubleToLongBits(longitude) != Double.doubleToLongBits(other.longitude)) return false; return true; } public String toString() { return "lat/lng: (" + this.latitude + "," + this.longitude + ")"; } }
計(jì)算工具類如下:
package amap; /** * 高德地圖工具 * * @author jianggujin * */ public class AMapUtils { /** * 根據(jù)用戶的起點(diǎn)和終點(diǎn)經(jīng)緯度計(jì)算兩點(diǎn)間距離,此距離為相對(duì)較短的距離,單位米。 * * @param start * 起點(diǎn)的坐標(biāo) * @param end * 終點(diǎn)的坐標(biāo) * @return */ public static double calculateLineDistance(LngLat start, LngLat end) { if ((start == null) || (end == null)) { throw new IllegalArgumentException("非法坐標(biāo)值,不能為null"); } double d1 = 0.01745329251994329D; double d2 = start.longitude; double d3 = start.latitude; double d4 = end.longitude; double d5 = end.latitude; d2 *= d1; d3 *= d1; d4 *= d1; d5 *= d1; double d6 = Math.sin(d2); double d7 = Math.sin(d3); double d8 = Math.cos(d2); double d9 = Math.cos(d3); double d10 = Math.sin(d4); double d11 = Math.sin(d5); double d12 = Math.cos(d4); double d13 = Math.cos(d5); double[] arrayOfDouble1 = new double[3]; double[] arrayOfDouble2 = new double[3]; arrayOfDouble1[0] = (d9 * d8); arrayOfDouble1[1] = (d9 * d6); arrayOfDouble1[2] = d7; arrayOfDouble2[0] = (d13 * d12); arrayOfDouble2[1] = (d13 * d10); arrayOfDouble2[2] = d11; double d14 = Math.sqrt((arrayOfDouble1[0] - arrayOfDouble2[0]) * (arrayOfDouble1[0] - arrayOfDouble2[0]) + (arrayOfDouble1[1] - arrayOfDouble2[1]) * (arrayOfDouble1[1] - arrayOfDouble2[1]) + (arrayOfDouble1[2] - arrayOfDouble2[2]) * (arrayOfDouble1[2] - arrayOfDouble2[2])); return (Math.asin(d14 / 2.0D) * 12742001.579854401D); } }
最后邊寫一段測(cè)試代碼測(cè)試一下:
package test; import org.junit.Test; import amap.AMapUtils; import amap.LngLat; public class AMapTest { @Test public void Test() { LngLat start = new LngLat(116.368904, 39.923423); LngLat end = new LngLat(116.387271, 39.922501); System.err.println(AMapUtils.calculateLineDistance(start, end)); } }
運(yùn)行結(jié)果為:1569.6213922679392,官網(wǎng)的javascript API示例結(jié)果如圖:
結(jié)果雖然有一點(diǎn)誤差,但是這hi在可接受范圍內(nèi)的。
Javascript實(shí)現(xiàn)
同樣的算法,將其轉(zhuǎn)換成JS的寫法,完整的代碼如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <script type="text/javascript" src="js/ajax.js"></script> <script> /** * 存儲(chǔ)經(jīng)緯度 * @param {Object} longitude * @param {Object} latitude */ function LngLat(longitude, latitude) { this.longitude = longitude; this.latitude = latitude; } function calculateLineDistance(start, end) { var d1 = 0.01745329251994329; var d2 = start.longitude; var d3 = start.latitude; var d4 = end.longitude; var d5 = end.latitude; d2 *= d1; d3 *= d1; d4 *= d1; d5 *= d1; var d6 = Math.sin(d2); var d7 = Math.sin(d3); var d8 = Math.cos(d2); var d9 = Math.cos(d3); var d10 = Math.sin(d4); var d11 = Math.sin(d5); var d12 = Math.cos(d4); var d13 = Math.cos(d5); var arrayOfDouble1 = []; var arrayOfDouble2 = []; arrayOfDouble1.push(d9 * d8); arrayOfDouble1.push(d9 * d6); arrayOfDouble1.push(d7); arrayOfDouble2.push(d13 * d12); arrayOfDouble2.push(d13 * d10); arrayOfDouble2.push(d11); var d14 = Math.sqrt((arrayOfDouble1[0] - arrayOfDouble2[0]) * (arrayOfDouble1[0] - arrayOfDouble2[0]) + (arrayOfDouble1[1] - arrayOfDouble2[1]) * (arrayOfDouble1[1] - arrayOfDouble2[1]) + (arrayOfDouble1[2] - arrayOfDouble2[2]) * (arrayOfDouble1[2] - arrayOfDouble2[2])); return(Math.asin(d14 / 2.0) * 12742001.579854401); } var start = new LngLat(116.368904, 39.923423); var end = new LngLat(116.387271, 39.922501); </script> </head> <body> <script> document.write(calculateLineDistance(start, end)); </script> </body> </html>
MySQL實(shí)現(xiàn)
DELIMITER $$ CREATE FUNCTION `calculateLineDistance`(startLng double, startLat double, endLng double, endLat double) RETURNS double BEGIN declare d2 DOUBLE; declare d3 DOUBLE; declare d4 DOUBLE; declare d5 DOUBLE; declare d6 DOUBLE; declare d7 DOUBLE; declare d8 DOUBLE; declare d9 DOUBLE; declare d10 DOUBLE; declare d11 DOUBLE; declare d12 DOUBLE; declare d13 DOUBLE; declare d14 DOUBLE; declare arrayOfDouble10 DOUBLE; declare arrayOfDouble11 DOUBLE; declare arrayOfDouble12 DOUBLe; declare arrayOfDouble20 DOUBLE; declare arrayOfDouble21 DOUBLE; declare arrayOfDouble22 DOUBLE; set d2 = startLng * 0.01745329251994329; set d3 = startLat * 0.01745329251994329; set d4 = endLng * 0.01745329251994329; set d5 = endLat * 0.01745329251994329; set d6 = sin(d2); set d7 = sin(d3); set d8 = cos(d2); set d9 = cos(d3); set d10 = sin(d4); set d11 = sin(d5); set d12 = cos(d4); set d13 = cos(d5); set arrayOfDouble10 = (d9 * d8); set arrayOfDouble11 = (d9 * d6); set arrayOfDouble12 = d7; set arrayOfDouble20 = (d13 * d12); set arrayOfDouble21 = (d13 * d10); set arrayOfDouble22 = d11; set d14 = sqrt((arrayOfDouble10 - arrayOfDouble20) * (arrayOfDouble10 - arrayOfDouble20) + (arrayOfDouble11 - arrayOfDouble21) * (arrayOfDouble11 - arrayOfDouble21) + (arrayOfDouble12 - arrayOfDouble22) * (arrayOfDouble12 - arrayOfDouble22)); return (asin(d14 / 2.0) * 12742001.579854401); END $$ DELIMITER ;
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- 微信JS-SDK坐標(biāo)位置如何轉(zhuǎn)換為百度地圖坐標(biāo)
- 基于JavaScript實(shí)現(xiàn)高德地圖和百度地圖提取行政區(qū)邊界經(jīng)緯度坐標(biāo)
- 通過(guò)百度地圖獲取公交線路的站點(diǎn)坐標(biāo)的js代碼
- JavaScript獲取對(duì)象在頁(yè)面中位置坐標(biāo)的方法
- javascript獲取文檔坐標(biāo)和視口坐標(biāo)
- js浮點(diǎn)數(shù)精確計(jì)算(加、減、乘、除)
- 根據(jù)經(jīng)緯度計(jì)算地球上兩點(diǎn)之間的距離js實(shí)現(xiàn)代碼
- 精通Javascript系列之?dāng)?shù)值計(jì)算
- js中火星坐標(biāo)、百度坐標(biāo)、WGS84坐標(biāo)轉(zhuǎn)換實(shí)現(xiàn)方法示例
相關(guān)文章
mybatis執(zhí)行錯(cuò)誤但sql執(zhí)行正常問(wèn)題
這篇文章主要介紹了mybatis執(zhí)行錯(cuò)誤但sql執(zhí)行正常問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01Spring boot學(xué)習(xí)教程之快速入門篇
這篇文章主要給大家介紹了關(guān)于Spring boot的相關(guān)資料,本文屬于基礎(chǔ)入門教程,對(duì)各位學(xué)習(xí)Spring boot的新手們具有一定的參考學(xué)習(xí)價(jià)值,,要的朋友們下面來(lái)一起看看吧。2017-04-04Java如何使用elasticsearch進(jìn)行模糊查詢
這篇文章主要介紹了Java如何使用elasticsearch進(jìn)行模糊查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02使用Java servlet實(shí)現(xiàn)自動(dòng)登錄退出功能
這篇文章主要介紹了使用Java servlet實(shí)現(xiàn)自動(dòng)登錄退出功能,,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11Mybatis中特殊SQL的執(zhí)行的實(shí)現(xiàn)示例
本文主要介紹了Mybatis中特殊SQL的執(zhí)行的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07基于Java事件監(jiān)聽編寫一個(gè)中秋猜燈謎小游戲
眾所周知,JavaSwing是Java中關(guān)于窗口開發(fā)的一個(gè)工具包,可以開發(fā)一些窗口程序,然后由于工具包的一些限制,導(dǎo)致Java在窗口開發(fā)商并沒有太多優(yōu)勢(shì),不過(guò),在JavaSwing中關(guān)于事件的監(jiān)聽機(jī)制是我們需要重點(diǎn)掌握的內(nèi)容,本文將基于Java事件監(jiān)聽編寫一個(gè)中秋猜燈謎小游戲2023-09-09Java實(shí)現(xiàn)解壓zip壓縮包的兩種方法(支持多層級(jí))
壓縮文件在生活中經(jīng)常能用到,在Java中提供了壓縮和解壓縮文件的功能,本文主要介紹了Java實(shí)現(xiàn)解壓zip壓縮包的兩種方法(支持多層級(jí)),感興趣的可以了解一下2024-03-03關(guān)于TransmittableThreadLocal線程池中線程復(fù)用問(wèn)題的解決方案
這篇文章主要介紹了關(guān)于TransmittableThreadLocal線程池中線程復(fù)用問(wèn)題的解決方案,線程池復(fù)用線程,如果子線程執(zhí)行完未移除上下文,則會(huì)導(dǎo)致后續(xù)線程可以取到之前線程設(shè)置的屬性,需要的朋友可以參考下2023-11-11