用postgresql(postgis) 查詢指定範圍內的興趣點
在地圖中一個任意經,緯度下點選.想要找到以這個點為中心指定半徑下包含多少個興趣點.
檢視postgis手冊找到了這麼一個函式(ST_Distance(geometry g1, geometry g2);)
官方文件上是這麼說的:
ST_Distance — For geometry type Returns the 2-dimensional cartesian minimum distance (based on spatial ref) between two geometries in projected units. For geography type defaults to return spheroidal minimum distance between two
geographies in meters.
即給定兩個空間點計算兩點間的距離.計算結果的單位與你的空間資料的參考系有關.
如果你使用的是4326(wgs84)這個座標系的話他是以度為單位的.要想轉成米為單位的話還得做一下轉換.下面會提到:
GEOCS代表的是地理座標系,也就是以經緯度表示的座標系統,例如4326
PROJCS代表的投影座標系,它是通過一種演算法把球面座標系轉成平面座標系,以便計算,一般是以米為單位表示, 例如26986
因此,在求兩點之間的距離時,由於存的資料都是經緯度,因此它參考的是GEOCS,要想得到以米為單位的結果,首先要把它轉成PROJCS,可以通過ST_Transform來實現
檢視postgis手冊 geometry ST_Transform
第一個引數是原來的幾何對像. 第二個引數為要把他轉換到這個投影所代表的做標系下.
這時我們只要找一個單位是米的投影做標系把他轉換過去就好了
例:
SELECT ST_Distance(
ST_Transform(ST_GeomFromText('POINT(-87.734087560562 43.770129071141)',4326),26986),
ST_Transform(ST_GeomFromText('POINT(-87.747382933006 43.759234252055)', 4326),26986)
);
這個查出來的結果即是以米為單位的兩點間的距離了
現在在說如何查詢一定範圍內的點
這裡用到了postgis裡的這第一個函式:boolean ST_DWithin(geometry g1, geometry g2, double precision distance_of_srid);
第一個引數為參考對像.第二個引數為目標對像.第三個引數為距離(同樣如果是地理座標系單位是度.投影做標系單位是米)
即以g1為中心,半徑為distance_of_srid,這個範圍內包不包含g2,如果包含反回true,否則即為假
如了給一個完整的例子.查詢以(-87.71 43.741)為中心半徑1516米範圍內的興趣點,之後按與這個中心點由近到遠的順序排列結果
SELECT t.feat_id,astext(t.geometry) FROM gis_site t
WHERE ST_DWithin(
ST_Transform(GeomFromText('POINT(-87.71 43.741)',4326),26986),
ST_Transform(t.geometry,26986), 1516)
ORDER BY ST_Distance(GeomFromText('POINT(-87.71 43.741)',4326), t.geometry);
結果:
24;"POINT(-87.718330082111 43.753078987035)"
17;"POINT(-87.726085716036 43.736952192682)"
18;"POINT(-87.726085716036 43.736952192682)"
找到了三個點