到目前為止,我們只使用了測量(ST_Area、ST_Length)、序列化(ST_GeomFromText)或者反序列化(ST_AsGML)幾何圖形(geometry)的空間函數。這些函數的共同之處在於它們一次只能處理一個幾何圖形。

空間資料庫之所以強大,是因為它們不僅能存儲幾何圖形,而且還能夠比較幾何圖形之間的關係

諸如"哪一個是離公園最近的自行車位?"或者"地鐵線路和街道的交叉路口在哪裡?"的問題,只能通過比較表示自行車位、街道和地鐵線路的幾何圖形來回答。

OGC標準定義了以下一組用於比較幾何圖形的方法。

一、ST_Equals

ST_Equals(geometry A, geometry B)用於測試兩個圖形的空間相等性。

如果兩個相同類型的幾何圖形具有相同的x、y坐標值,即如果第二個圖形與第一個圖形的坐標信息相等(相同),則ST_Equals()返回TRUE

首先,讓我們從nyc_subway_stations表中檢索點數據,我們只選"Broad St"的條目。

SELECT name, geom, ST_AsText(geom)
FROM nyc_subway_stations
WHERE name = Broad St;

然後,將幾何圖形表示數據插入ST_Equals()進行測試:

SELECT name
FROM nyc_subway_stations
WHERE ST_Equals(geom, 0101000020266900000EEBD4CF27CF2141BC17D69516315141);

注意:點在空間數據表中的表示不是很容易理解(0101000020266900000EEBD4CF27CF2141BC17D69516315141),但它是坐標值的精確表示。對於像相等這樣的測試,使用精確的坐標信息進行比較是必要的。

二、ST_Intersects、ST_Disjoint、ST_Crosses和ST_Overlaps

ST_IntersectsST_CrossesST_Overlaps測試幾何圖形是否相交。

如果兩個圖形有相同的部分,即如果它們的邊界或內部相交,則ST_Intersects(geometry A, geometry B)返回TRUE。

ST_Intersects()方法的對立方法是ST_Disjoint(geometry A, geometry B)

如果兩個幾何圖形沒有重合的部分,則它們不相交,反之亦然。

事實上測試"not intersect"通常比測試"disjoint"更有效,因為intersect測試可以使用空間索引

對於multipoint/polygon、multipoint/linestring、linestring/linestring、linestring/polygon和linestring/multipolygon的比較,如果相交生成的幾何圖形的維度小於兩個源幾何圖形的最大維度,且相交集位於兩個源幾何圖形的內部,則ST_Crosses(geometry A, geometry B)將返回TRUE。

ST_Overlaps(geometry A, geometry B)比較兩個相同維度的幾何圖形,如果它們的結果集與兩個源幾何圖形都不同但具有相同維度,則返回TRUE。

讓我們以寬街地鐵站(Broad Street subway station)為例,使用ST_Intersects()函數確定其所在社區:

SELECT name, ST_AsText(geom)
FROM nyc_subway_stations
WHERE name = Broad St;

SELECT name, boroname
FROM nyc_neighborhoods
WHERE ST_Intersects(geom, ST_GeomFromText(POINT(583571 4506714),26918));

三、ST_Touches

ST_Touches()測試兩個幾何圖形是否在它們的邊界上接觸,但在它們的內部不相交。

如果兩個幾何圖形的邊界相交,或者只有一個幾何圖形的內部與另一個幾何圖形的邊界相交,則ST_Touches(geometry A, geometry B)將返回TRUE。

四、ST_Within和ST_Contains

ST_Within()和ST_Contains()測試一個幾何圖形是否完全位於另一個幾何圖形內。

如果第一個幾何圖形完全位於第二個幾何圖形內,則ST_Within(geometry A, geometry B)返回TRUE,ST_Within()測試的結果與ST_Contains()完全相反。

如果第二個幾何圖形完全包含在第一個幾何圖形內,則ST_Contains(geometry A, geometry B)返回TRUE。

五、ST_Distance和ST_DWithin

一個常見的GIS問題是"找到這個物體周圍距離X的所有其他物體"。

ST_Distance(geometry A, geometry B)計算兩個幾何圖形之間的最短距離,並將其作為浮點數返回。這對於實際報告幾何圖形之間的距離非常有用。

SELECT ST_Distance(
ST_GeometryFromText(POINT(0 5)),
ST_GeometryFromText(LINESTRING(-2 2, 2 2)));

為了測試兩個幾何圖形之間的距離是否在某個範圍之內,ST_DWithin()函數提供了一個這樣的的功能。

這對於"在距離道路500米的緩衝區內有多少棵樹?"這樣的問題很有用,你不必計算實際的緩衝區,只需測試距離關係即可。

再次使用我們的寬街地鐵站(Broad Street subway station),我們可以找到地鐵站附近(10米內)的街道:

SELECT name
FROM nyc_streets
WHERE ST_DWithin(
geom,
ST_GeomFromText(POINT(583571 4506714),26918),
10
);

我們可以在地圖上驗證答案,Broad St站實際上是在Wall、Broad和Nassau街道的十字路口。

六、空間關係練習

下面是我們在文章上面部分涉及到的一些函數,它們應該對練習有用!

還請記住我們現在資料庫中已經具有的表:

  • nyc_census_blocks
    • blkid, popn_total, boroname, geom
  • nyc_streets
    • name, type, geom
  • nyc_subway_stations
    • name, geom
  • nyc_neighborhoods
    • name, boroname, geom

練習

①名為"Atlantic Commonts"的街道的geometry值是什麼?

SELECT ST_AsText(geom)
FROM nyc_streets
WHERE name = Atlantic Commons;

②Atlantic Commons(大西洋公地)位於哪個社區(neighborhood)和行政區(borough)?

SELECT name, boroname
FROM nyc_neighborhoods
WHERE ST_Intersects(
geom,
ST_GeomFromText(LINESTRING(586782 4504202,586864 4504216), 26918)
);

注意:嘿,為什麼要將"MULTILINESTRING"變成"LINESTRING"呢?因為在空間上,它們描述的是相同的形狀。

更重要的是,我們還對坐標進行了四捨五入,以使它們更易於閱讀,這實際上改變了結果:我們現在不能使用ST_Touches()方法來找出哪些道路連接Atlantic Commons,因為坐標不再與原來的坐標完全相同。

③Atlantic Commons與哪些街道相連?

SELECT name
FROM nyc_streets
WHERE ST_DWithin(
geom,
ST_GeomFromText(LINESTRING(586782 4504202,586864 4504216), 26918),
0.1
);

④大約有多少人住在Atlantic Commons上(距離Atlantic Commons50米以內)?

SELECT Sum(popn_total)
FROM nyc_census_blocks
WHERE ST_DWithin(
geom,
ST_GeomFromText(LINESTRING(586782 4504202,586864 4504216), 26918),
50
);

推薦閱讀:

相关文章