postgresql 計算距離

原文鏈接:https://blog.csdn.net/weixin_36343850/article/details/87977317

背景:PostgreSQL 可以擴展PostGIS 模塊,來完成地理空間計算方面的任務
問題描述:使用內(nèi)置函數(shù) ST_Length來計算軌跡長度時,發(fā)現(xiàn)計算的結(jié)果和實際不太符合,查閱相關(guān)博客發(fā)現(xiàn)原來是坐標系的問題。(但是各個博客的內(nèi)容可能不太準確,折騰了半天,最后找到官網(wǎng),成功把問題解決,只能說,官網(wǎng)是個好東西)
問題解決:
概念: geometry和geography的區(qū)別

  • geometry:planar 平面坐標系【supported by SQL Server conforms to the Open Geospatial Consortium (OGC) Simple Features for SQL Specification version 1.1.0.】
  • geography: terrestrial 地理坐標系【stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.】
    也就是說,geometry是一個平面幾何的概念,而geography是一個地球的地理的概念。所以當兩個點形成一條軌跡時,輸入經(jīng)緯度直接采用geometry即幾何的方法來算的話,會不準,因為地球是一個球體,而不是一個簡單的平面。
    ST_Length函數(shù)的使用

先來看看官網(wǎng)的描述(點擊藍色的兩個字可以直達官網(wǎng)):

ST_Length — Returns the 2D length of the geometry if it is a LineString or MultiLineString. geometry are in units of spatial reference and geography are in meters (default spheroid)

輸入LineString 或者 MultiLineString 格式的數(shù)據(jù),然后返回二維的長度。對于geometry類型,返回對應空間參考系的單位,對于geography返回以米為單位。

再看看函數(shù)定義
float ST_Length(geometry a_2dlinestring);
float ST_Length(geography geog, boolean use_spheroid=true);

很明顯,是分為兩種輸入類型來的。兩種不同的輸入返回輸入的結(jié)果。而對于geography 類型的use_spheroid這個參數(shù),默認為true,用來指定是否使用參考面(因為地圖是個不規(guī)則球體,有各種參考面),如果為false,則不使用參考面,把地球當做一個完美的球體來看待,因而精度會降低,但是能剩下不少計算的時間。

具體解決辦法
回歸到問題, 直接把LineString 或 MultiLineString輸入函數(shù),屬于 geometry 類型,所以如果是計算地理上面的數(shù)據(jù),是不準確的。因此,使用ST_GeographyFromText函數(shù)將數(shù)據(jù)從geometry 類型轉(zhuǎn)換為geography ,然后再進行計算,調(diào)用的就是第二個方法,得到正確的結(jié)果。
官網(wǎng)示例:

SELECT ST_Length(the_geog) As length_spheroid,  
ST_Length(the_geog,false) As length_sphere
FROM  (
SELECT ST_GeographyFromText('SRID=4326;LINESTRING(-72.1260 42.45, -72.1240 42.45666, -72.123 42.1546)') As the_geog ) As foo;

結(jié)果:

length_spheroid | length_sphere
------------------±-----------------
34310.5703627288 | 34346.2060960742

個人示例:

查看原始數(shù)據(jù)

SELECT gid,geom FROM bfmap_ways limit 10;

從上圖可以看到,原始數(shù)據(jù)有兩個字段,gid和geom,其中g(shù)eom是二進制格式。

使用st_astext將二進制格式轉(zhuǎn)換為文本格式,然后使用ST_GeographyFromText將數(shù)據(jù)轉(zhuǎn)換為Geography格式,最后用st_length計算長度

SELECT gid, st_astext(geom) as geom,
st_length(ST_GeographyFromText(st_astext(geom))) as length 
FROM bfmap_ways limit 10;

總結(jié):不清楚的時候,盡可能去找官網(wǎng)!官網(wǎng)的描述最準確,最詳細!最后再一次附上官網(wǎng) http://postgis.net/docs/manual-2.3/ST_Length.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容