美國(guó)人在床上做裸身體網(wǎng)站啊軟文投放平臺(tái)有哪些?
目錄
前言
一、空間數(shù)據(jù)庫(kù)求解
1、PostGIS實(shí)現(xiàn)
二、GIS前端組件求解
1、Leaflet.js距離測(cè)算
2、Turf.js前端計(jì)算?
三、后臺(tái)距離計(jì)算生成?
1、歐式距離
2、Haversice球面距離
3、GeoTools距離計(jì)算
4、Gdal距離生成
? 5、geodesy距離計(jì)算
四、成果與生成對(duì)比
1、Java不同生成方法對(duì)比
2、各種生成方式對(duì)比
五、總結(jié)
前言
????????空間距離是指物體在空間中的位置之間的距離,通常用來描述物體之間的相對(duì)位置關(guān)系。在日常生活中,我們經(jīng)常使用距離來描述物體的位置關(guān)系,比如在行駛中使用路程來描述兩個(gè)地點(diǎn)之間的距離,或者在導(dǎo)航中使用地圖上的距離來指引行駛方向。在物理學(xué)和數(shù)學(xué)中,距離是一個(gè)重要的概念,它被用來描述空間中的位置關(guān)系,衡量物體之間的遠(yuǎn)近??臻g距離的研究對(duì)于理解物體的位置關(guān)系、運(yùn)動(dòng)軌跡、引力場(chǎng)等具有重要的意義。下面是在某地圖軟件中,使用測(cè)距的方式直接量算的長(zhǎng)度示例。
? ? ? ? 在地理世界中,在導(dǎo)航系統(tǒng)中,物流系統(tǒng)中,旅游景點(diǎn)等應(yīng)用。距離這個(gè)概念更是非常常見的,比如在導(dǎo)航系統(tǒng)中,從家到某商場(chǎng)的距離;在快遞物流行業(yè)中,我們從浙江義烏的小商品城購(gòu)買一件物品,然后郵寄到家;還可能我們計(jì)劃出門旅游,那么我們想知道家到目的地的實(shí)際距離有多遠(yuǎn)等等場(chǎng)景,都是非常具有代表性的距離求解和應(yīng)用場(chǎng)景。
????????伴隨著生活的不斷進(jìn)步,在我們的生活中,我們會(huì)應(yīng)用更多距離計(jì)算。作為一位GIS開發(fā)者,距離是空間分析中最簡(jiǎn)單的一種類型。本文將詳細(xì)的講解各種不同位置距離計(jì)算方法,首先講解使用空間數(shù)據(jù)庫(kù)的直接求解辦法,其次介紹在前端組件如Leaflet.js、Turf.js等組件中進(jìn)行求解的辦法,然后基于Java語(yǔ)言講解后端的詳細(xì)計(jì)算方法,包括Java直接求解、GeoTools計(jì)算、geodesy距離計(jì)算、歐式距離計(jì)算、GDAL空間計(jì)算等不同的方法,最后對(duì)比不同的計(jì)算方法得到的結(jié)果,為大家對(duì)距離的計(jì)算有更多的掌握和了解。
一、空間數(shù)據(jù)庫(kù)求解
????????在進(jìn)行空間距離求解時(shí),我們這里假定一種場(chǎng)景。比如以共享單車為例,需要計(jì)算從起始點(diǎn)到結(jié)束點(diǎn)的距離,這里涉及到兩個(gè)信息,也就是已知兩個(gè)經(jīng)緯度坐標(biāo)點(diǎn),即:和
,在給定兩個(gè)包含經(jīng)緯度坐標(biāo)的點(diǎn)后,我們來求解其距離。我們計(jì)算從某公園的一角到地鐵站的距離,首先我們?cè)诘貓D上將這個(gè)點(diǎn)標(biāo)記出來,得到這兩點(diǎn)的實(shí)際經(jīng)緯度。實(shí)現(xiàn)方法是在Leaflet中綁定點(diǎn)擊事件,然后在點(diǎn)擊事件中輸出具體的坐標(biāo)。
????????在地圖上標(biāo)記出兩個(gè)位置,得到需要計(jì)算的兩個(gè)點(diǎn)的具體經(jīng)緯度信息:????????????????????????????????和
。
表示起點(diǎn),
表示目的地。后續(xù)的計(jì)算均以這兩個(gè)坐標(biāo)點(diǎn)為起始位置。
1、PostGIS實(shí)現(xiàn)
????????為了簡(jiǎn)單起見,這里的空間數(shù)據(jù)庫(kù)實(shí)現(xiàn),我們采用PostGIS來進(jìn)行開發(fā)數(shù)據(jù)庫(kù)。當(dāng)然在實(shí)際開發(fā)過程中,除了可以選擇PostGIS數(shù)據(jù)庫(kù),還可以選擇其它的空間數(shù)據(jù)庫(kù),比如MySQL或者Oracle SDE等。在PostGIS數(shù)據(jù)庫(kù)中,我們可以使用ST_Distance()和ST_GeomFromText()進(jìn)行查詢,首先使用ST_GeomFromText()將字符串轉(zhuǎn)換為Geography,然后再使用ST_Distance()來進(jìn)行記錄求解,請(qǐng)注意,在進(jìn)行求解時(shí),務(wù)必保證安裝PostGIS擴(kuò)展。
SELECTST_Distance ( ST_GeomFromText ( 'POINT(112.867699 28.194674)', 4326 ) :: geography, ST_GeomFromText ( 'POINT(112.876024 28.189038)', 4326 ) :: geography
) AS distance;
????????這里選擇將geometry轉(zhuǎn)換為geography字段是為了將輸出的結(jié)果轉(zhuǎn)換為常見的距離單位,米。在postgis中,會(huì)自動(dòng)根據(jù)不同的投影類型來得到距離結(jié)果,如果用4326的參考系,得到的結(jié)果將是度。 在PostGIS中使用空間數(shù)據(jù)庫(kù)的方式的消耗時(shí)間大約是:3毫秒,兩點(diǎn)間的測(cè)算距離是1028.7251米。速度也是非常快的。
二、GIS前端組件求解
????????在介紹完空間數(shù)據(jù)庫(kù)的求解模式后。接下來我們介紹一下基于WebGIS的前端組件求解方式。這種解決方式比較適用于以前端為主的應(yīng)用中,不需要數(shù)據(jù)庫(kù)的支持。常見的WebGIS前端組件也有許多,二維常見的有Leaflet、OpenLayers等,三維有Cesium等。這里我們已Leaflet為例,同時(shí)講解在Turf.js中是如何實(shí)現(xiàn)的。
1、Leaflet.js距離測(cè)算
????????首先來看一下再Leaflet.js中進(jìn)行距離的計(jì)算,得到的結(jié)果是多少。首先我們需要在頁(yè)面中引用到Leaflet.js,可以是本地的離線資源,也可以是在線資源。可以直接使用Leaflet.js的相關(guān)API來進(jìn)行。關(guān)鍵代碼如下:
let latlng1 = L.latLng(28.194674, 112.867699);
// 第二個(gè)點(diǎn)
let latlng2 = L.latLng(28.189038, 112.876024);
// 計(jì)算兩點(diǎn)之間的距離
let distance = latlng1.distanceTo(latlng2);
????????使用Leaflet的距離求解方法得到的距離是:1028.79098米,耗時(shí)5毫秒。
2、Turf.js前端計(jì)算?
????????Turf.js也是一款在WebGIS系統(tǒng)開發(fā)當(dāng)中很常見的前端計(jì)算框架,在之前的一些博客中曾經(jīng)做了比較詳細(xì)的介紹,關(guān)于turf.js,它就像一個(gè)寶藏一樣,值得我們?nèi)W(xué)習(xí)研究,發(fā)現(xiàn)更多的實(shí)用功能。turf可以和Leaflet或者openLayers,cesium等配合使用。這里重點(diǎn)講解如何使用Turf.js來進(jìn)行距離運(yùn)算。關(guān)鍵代碼如下:
var from = turf.point([112.867699,28.194674]);
var to = turf.point([112.876024,28.189038]);
var options = { units: "meters" };//設(shè)置單位為米
var distance = turf.distance(from, to, options);//求解計(jì)算
????????使用Turf.js的距離求解方法得到的距離是:1028.7924米,耗時(shí)4毫秒。
三、后臺(tái)距離計(jì)算生成?
????????在了解空間數(shù)據(jù)庫(kù)生成和WebGIS前端組件生成方式之后,我們來看一下如何使用后臺(tái)服務(wù)的生成方式。這里以Java開發(fā)語(yǔ)言為例,主要介紹如何使用Java來進(jìn)行不同的距離進(jìn)行生成。包括但不限于歐式距離、球面距離、GeoTools距離生成、Gdal距離生成、Geodesy距離生成等。
1、歐式距離
????????歐式距離(Euclidean distance)是最直接距離度量方式,用于計(jì)算兩個(gè)點(diǎn)在歐幾里得空間中的直線距離,如果有兩個(gè)點(diǎn):和
在二維空間中,它們之間的歐式距離d 可以通過下面的公式來計(jì)算:
????????根據(jù)上面的公式定義,可以直接使用Java原始的計(jì)算方式來計(jì)算,關(guān)鍵代碼如下所示:
/**
* 計(jì)算兩點(diǎn)的歐式距離
* @param p0 起始點(diǎn)
* @param p1 結(jié)束點(diǎn)
* @return
*/
public static double calculateEuclideanDistance(Coordinate p0, Coordinate p1) {Long start = System.currentTimeMillis();double result = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2));Long end= System.currentTimeMillis();System.out.println("計(jì)算耗時(shí):" + ( end - start) + "毫秒");return result;}
2、Haversice球面距離
????????Haversice公式,通過兩點(diǎn)計(jì)算大圓距離,(即球面上兩點(diǎn)的最短距離),Haversice的數(shù)學(xué)表達(dá):設(shè)兩點(diǎn)的經(jīng)緯度分別為(lat1,lon1)和(lat2,lon2),其中經(jīng)度和緯度以弧度為單位。地球的平均半徑R約為6371公里。Haversice的計(jì)算步驟為:
????????首先將經(jīng)緯度從度數(shù)轉(zhuǎn)換為弧度(考慮曲率)。lat1,lon1,lat2,lon2 ->rad。然后計(jì)算經(jīng)度和緯度的差值,以及
,最后使用下面的公式計(jì)算距離:
d=R * c
????????在上面的公式中,d表示兩點(diǎn)間的距離。將上述公式轉(zhuǎn)換為代碼后如下所示:
/*** 計(jì)算兩個(gè)位置的球面距離* @param p0 起始點(diǎn)* @param p1 目標(biāo)點(diǎn)* @return*/
public static double calculateHaversineDistance(Coordinate p0, Coordinate p1) {Long start = System.currentTimeMillis();double radLat1 = Math.toRadians(p0.x);double radLon1 = Math.toRadians(p0.y);double radLat2 = Math.toRadians(p1.x);double radLon2 = Math.toRadians(p1.y);double deltaLat = radLat2 - radLat1;double deltaLon = radLon2 - radLon1;double a = Math.pow(Math.sin(deltaLat / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) *Math.pow(Math.sin(deltaLon / 2), 2);double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));double distance = EARTH_RADIUS * c;Long end= System.currentTimeMillis();System.out.println("計(jì)算耗時(shí):" + ( end - start) + "毫秒");return distance;
}
3、GeoTools距離計(jì)算
????????我們可以直接利用GeoTools來直接進(jìn)行距離的計(jì)算,它以API的方式直接提供調(diào)用,這里我們不深入核心的計(jì)算方法,具體大家可以深入源碼去看。示例的關(guān)鍵代碼如下:
/**
* 使用Geotools來求解距離使用WGS84參考系
* @param p0 起始點(diǎn)
* @param p1 目標(biāo)點(diǎn)
* @return
*/
public static double geoToolsDistanceWithWgs84Crs(Coordinate p0, Coordinate p1) {Long start = System.currentTimeMillis();// 84坐標(biāo)系構(gòu)造GeodeticCalculatorGeodeticCalculator geodeticCalculator = new GeodeticCalculator(DefaultGeographicCRS.WGS84);// 起點(diǎn)經(jīng)緯度geodeticCalculator.setStartingGeographicPoint(p0.x, p0.y);// 末點(diǎn)經(jīng)緯度geodeticCalculator.setDestinationGeographicPoint(p1.x, p1.y);// 計(jì)算距離,單位:米double result = geodeticCalculator.getOrthodromicDistance();Long end= System.currentTimeMillis();System.out.println("計(jì)算耗時(shí):" + ( end - start) + "毫秒");return result;}
4、Gdal距離生成
????????與GeoTools類似,在Java開發(fā)當(dāng)中,除了可以使用GeoTools中進(jìn)行距離計(jì)算。Gdal也是同樣可以進(jìn)行距離計(jì)算的。???
/*** 使用gdal來計(jì)算兩個(gè)點(diǎn)距離* @param p0 起始點(diǎn)* @param p1 目標(biāo)點(diǎn)* @return*/public static double calculateGdalDistance(Coordinate p0, Coordinate p1) {Long start = System.currentTimeMillis();// 注冊(cè)所有的GDAL驅(qū)動(dòng)gdal.AllRegister();// 創(chuàng)建兩個(gè)點(diǎn)的幾何對(duì)象Geometry point1 = ogr.CreateGeometryFromWkt("POINT ("+ p0.y+" "+p0.x+")");Geometry point2 = ogr.CreateGeometryFromWkt("POINT ("+ p1.y+" "+p1.x+")");// 創(chuàng)建空間參考對(duì)象SpatialReference srs = new SpatialReference();// 導(dǎo)入WGS84坐標(biāo)系的EPSG代碼srs.ImportFromEPSG(4326);// 為幾何對(duì)象設(shè)置空間參考point1.AssignSpatialReference(srs);point2.AssignSpatialReference(srs);// 計(jì)算兩個(gè)點(diǎn)之間的距離double distance = point1.Distance(point2);// 輸出距離,注意GDAL返回的距離單位可能與坐標(biāo)系單位不同,需要根據(jù)實(shí)際情況轉(zhuǎn)換System.out.println("Distance: " + distance);Long end= System.currentTimeMillis();System.out.println("計(jì)算耗時(shí):" + ( end - start) + "毫秒");return distance;
}
? 5、geodesy距離計(jì)算
????????與Gdal與GeoTools不同,geodesy是一個(gè)輕量級(jí)的地理分析和處理框架。因此我們可以可以使用geodesy來進(jìn)行距離的計(jì)算,關(guān)鍵計(jì)算過程如下所示:
/*** 使用geodesy來計(jì)算兩個(gè)點(diǎn)距離* @param p0 起始點(diǎn)* @param p1 目標(biāo)點(diǎn)* @return*/public static double calculateGeodesyDistance(Coordinate p0, Coordinate p1) {Long start = System.currentTimeMillis();//創(chuàng)建GeodeticCalculator,調(diào)用計(jì)算方法,傳入坐標(biāo)系、經(jīng)緯度用于計(jì)算距離GeodeticCurve geoCurve = new org.gavaghan.geodesy.GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.WGS84,new GlobalCoordinates(p0.x, p0.y),new GlobalCoordinates(p1.x, p1.y));double result = geoCurve.getEllipsoidalDistance();Long end= System.currentTimeMillis();System.out.println("計(jì)算耗時(shí):" + ( end - start) + "毫秒");return result;
}
????????以上就是5種使用java生成距離的方式,通過以上的代碼均可生成距離。
四、成果與生成對(duì)比
????????這里將對(duì)生成的距離成果與不同的生成方式進(jìn)行對(duì)比,方便大家對(duì)結(jié)果和生成過程有一個(gè)具體的認(rèn)識(shí)。
1、Java不同生成方法對(duì)比
????????我們以Junit代碼為例,分別調(diào)用上述的代碼,用來計(jì)算兩個(gè)點(diǎn)的距離和生成時(shí)間。代碼如下:
@Test
public void testGeoToolsDis() {Coordinate coord1 = new Coordinate(112.867699, 28.194674); //出發(fā)的位置Coordinate coord2 = new Coordinate(112.876024, 28.189038); // 到達(dá)的經(jīng)緯度 double distance = geoToolsDistanceWithDefaultCrs(coord1, coord2);System.out.println("geotools Distance no crs: " + distance + " meters");System.out.println("********************************************");distance = geoToolsDistanceWithWgs84Crs(coord1,coord2);System.out.println("geotools Distance crs: " + distance + " meters");System.out.println("********************************************");double distance1 = calculateEuclideanDistance(coord1,coord2);System.out.println("歐式距離(度):" + distance1);distance = distance1 * EARTH_RADIUS * Math.PI / 180 * 1000;System.out.println("歐式距離(米):" + distance + " meters");System.out.println("********************************************");distance = calculateHaversineDistance(coord1,coord2) * 1000;System.out.println("球面距離:Haversine Distance: " + distance + " meters");System.out.println("********************************************");distance = calculateGeodesyDistance(coord1,coord2);System.out.println("Geodesy Distance: " + distance + " meters");System.out.println("********************************************");distance = calculateGdalDistance(coord1,coord2);distance = distance * EARTH_RADIUS * Math.PI / 180 * 1000;System.out.println("Gdal Distance: " + distance + " meters");
}
????????可以控制臺(tái)看到以下的輸出:
計(jì)算耗時(shí):230毫秒
geotools Distance no crs: 1028.725087712003 meters
********************************************
計(jì)算耗時(shí):1790毫秒
geotools Distance crs: 1028.725087712003 meters
********************************************
計(jì)算耗時(shí):0毫秒
歐式距離(度):0.010053363665956643
歐式距離(米):1119.1353240538915 meters
********************************************
計(jì)算耗時(shí):0毫秒
球面距離:Haversine Distance: 958.2800850973537 meters
********************************************
計(jì)算耗時(shí):5毫秒
Geodesy Distance: 960.1006447758463 meters
********************************************
Distance: 0.010053363665956643
計(jì)算耗時(shí):336毫秒
Gdal Distance: 1119.1353240538915 meters
????????請(qǐng)注意,在上面的計(jì)算過程中,使用歐式距離是,首先生成出來的是度,而不是我們的預(yù)期米。因此需要進(jìn)行轉(zhuǎn)換。轉(zhuǎn)換代碼可以參考上面的示例代碼。
2、各種生成方式對(duì)比
????????這里將提供兩種數(shù)據(jù)結(jié)果對(duì)比,第一種是提供表格的形式,第二種是提供圖表的形式。如下表所示:
序號(hào) | 生成方式 | 生成距離(米) | 耗時(shí)(毫秒) |
1 | PostGIS數(shù)據(jù)庫(kù) | 1028.72508 | 3 |
2 | Leaflet.js | 1028.79098 | 5 |
3 | Turf.js | 1028.7924 | 4 |
4 | GeoTools no Crs | 1028.725087 | 230 |
5 | GeoTools with Crs | 1028.725087 | 1790 |
6 | 歐式距離 | 1119.13532 | 接近0 |
7 | Haversine距離 | 958.28008 | 接近0 |
8 | Geodesy | 960.10064 | 5 |
9 | Gdal 距離 | 1119.13532 | 336 |
????????將上面的各種距離生成結(jié)果使用圖表的形式來展示,如下所示:
五、總結(jié)
????????以上就是本文的主要內(nèi)容,本文將詳細(xì)的講解各種不同位置距離計(jì)算方法,首先講解使用空間數(shù)據(jù)庫(kù)的直接求解辦法,其次介紹在前端組件如Leaflet.js、Turf.js等組件中進(jìn)行求解的辦法,然后基于Java語(yǔ)言講解后端的詳細(xì)計(jì)算方法,包括Java直接求解、GeoTools計(jì)算、geodesy距離計(jì)算、歐式距離計(jì)算、GDAL空間計(jì)算等不同的方法,最后對(duì)比不同的計(jì)算方法得到的結(jié)果,為大家對(duì)距離的計(jì)算有更多的掌握和了解。行文倉(cāng)促,定有許多不足之處,如有不足,還請(qǐng)各位專家博主在評(píng)論區(qū)留言指出,不勝感激。