1. 程式人生 > >postgresql+postgis空間資料庫使用總結

postgresql+postgis空間資料庫使用總結

參考資料: pgrouting路徑導航 線上轉換shp和json格式圖形化工具 pgsql語法 pgsql幾何型別的使用 pgsql判斷點是否在面內 PostGIS的Geometry資料型別 Geometry可以說是PostGIS最重要的一個概念,是“幾何體”的意思,由於PostGIS很 好地遵守OGC的”Simple Feature for Specification for SQL”規範,目前支援的幾何體型別包含其例項有WKT格式如下: POINT(1 1) MULTIPOINT(1 1, 3 4, -1 3) LINESTRING(1 1, 2 2, 3 4) POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))
MULTIPOLYGON((0 0, 0 1, 1 1, 1 0, 0 0), (5 5, 5 6, 6 6, 6 5, 5 5)) MULTILINESTRING((1 1, 2 2, 3 4),(2 2, 3 3, 4 5)) 而geometry具體表現又有兩種形式,一種叫做WKT(Well Known Text)形式,如上面的 例子。或者使用如下SQL語句瀏覽: select AsText(pt) from test1; 另一種叫做“Canonical Form”形式,看上去是一串古怪的數字,其實是一種增強的十六 進位制編碼,使用如下SQL語句就可以瀏覽了: select pt from test1;
EWKT、EWKB和Canonical格式 EWKT和EWKB相比OGC WKT和WKB格式主要的擴充套件有3DZ、3DM、4D座標和內嵌空間參考支援。 以下以EWKT語句定義了一些幾何物件: POINT(0 0 0) ——3D點 SRID=32632;POINT(0 0) ——內嵌空間參考的點 POINTM(0 0 0) ——帶M值的點 POINT(0 0 0 0) ——帶M值的3D點 SRID=4326;MULTIPOINTM(0 0 0,1 2 1) ——內嵌空間參考的帶M值的多點 以下語句可以使用EWKT格式插入一個點要素到一個表中: INSERT INTO table ( SHAPE, NAME ) VALUES ( GeomFromEWKT('SRID=4326;POINTM(116.39 39.9 10)'), '北京' )
Canonical格式是16進位制編碼的幾何物件,直接用SQL語句查詢出來的就是這種格式。 postgis3d空間語法以及函式應用: 網上關於postgis的函式有很多,這裡簡單使用幾個我用的到的函式進行測試 在執行幾何型別的sql語句的時候一定要注意型別的轉換、表空間列的屬性或者使用適當的型別,不然執行會報錯,下面的sql語句親測沒有任何問題 插入: insert into SSS(geometryType) values(ST_GeomFromText('POINTZ(116.39 21 39.9)', 4326)); 修改: UPDATE eee SET geometryType = ST_GeomFromText('POINTM(116.39 21 39.9)',4326) 新增: CREATE TABLE weq (id serial PRIMARY KEY, details VARCHAR(10000), template VARCHAR(255), create_time VARCHAR(255), modeUrl VARCHAR(255), geoJson VARCHAR(255), geometryType geometry(POINTM,4326)) A是否包含B,包含返回t,不包含返回f SELECT ST_Contains(st_astext(geometrytype),'POINTZ(151 50 30)') FROM videodata 找到 POINT(1000 1000) 100米範圍內的查詢如下: SELECT * FROM geotable WHERE ST_DWithin(geocolumn, ‘POINT(1000 1000)’, 100.0); 查詢點在面內,包含返回t,不包含返回f SELECT ST_Contains(st_astext(ST_MakePolygon(ST_GeomFromText('LINESTRINGZ (0 0 1,0 2 1,2 2 1,2 0 1,0 0 1) '))),'POINTZ(1 1 5)') 或者 SELECT ST_Contains( ST_MakePolygon(ST_GeomFromText(ST_ASTEXT(geometrytype))),st_pointz(0,0,0)) FROM videodata 點是否在面內,包含返回t,不包含返回f sql語句如下: select * from tb_data_region_polygon0 where ST_Within(st_geomfromtext('point(114.186684 30.512029)',4326),geom); select * from tb_data_region_polygon0 where ST_DWithin(st_geomfromtext('point(114.186684 30.512029)',4326),geom,0); select * from tb_data_region_polygon0 where ST_Covers(geom,st_geomfromtext('point(114.186684 30.512029)',4326)); postgis 中 geomery 使用 ST_distance 計算出來的單位竟然是弧度,不是米,找了一段時間問題,發現是沒有使用投影座標引起的 於是在計算的時候,先將點變成投影座標,再來計算。 使用ST_Transform(geom, 2346)轉換之後就是以米為單位的資料了 結果以米為單位(計算長度): SELECT ST_Length(ST_Transform(geom, 2346)) FROM ditie 這裡的2346中國西安80高絲克里投影的編號,是分帶的,使用的中央經線在南京。 加上這個,我們能正確計算出來距離,也是米。 但是如果把應用發到別的城市,比如蘇州,就會出現問題,解決方法: 查詢ditie表點到每個線的距離,條件是在80000米之內的點 select (ST_distance( geom::geography, ST_GeomFromText('POINT(121 32)', 4326)::geography)) from ditie where ST_dwithin(geom::geography, ST_GeomFromText('POINT(121 32)', 4326)::geography, 80000) 這樣把geometry轉成geography,轉換之後,全球都可以使用了 下面這種辦法查出來的結果也是以米為單位的兩點間的距離 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) );  在專案中,我們也可以直接把座標存成 geography格式的,這樣就能避免資料轉來轉去的了: ST_GeographyFromText('SRID=4326;POINT(-110 30)') 改變表的空間欄位srid為4326 update table_name set the_geom = st_geomfromtext(ST_AsText(the_geom),4326)