簡體   English   中英

SQL Server 2008 空間:在多邊形中找到一個點

[英]SQL Server 2008 Spatial: find a point in polygon

我正在使用 SQL Server 2008 空間數據類型。 我有一個表,其中包含所有狀態(作為多邊形)作為數據類型 GEOMETRY。 現在我想檢查一個點的坐標(緯度、經度)作為數據類型 GEOGRAPHY 是否在該州內。

我找不到任何使用新空間數據類型的示例。 目前,我有一個多年前實施的解決方法,但它有一些缺點。

我有 SQL Server 2008 和 2012。如果新版本有一些改進,我也可以開始使用它。

謝謝。

更新1:

我正在添加一個代碼示例,以便更加清晰。

declare @s geometry  --GeomCol is of this type too.
declare @z geography --GeogCol is of this type too.

select @s = GeomCol
from AllStates
where STATE_ABBR = 'NY'

select @z = GeogCol
from AllZipCodes
where ZipCode = 10101

我認為地理方法 STIntersects() 會做你想做的:

DECLARE @g geography;
DECLARE @h geography;
SET @g = geography::STGeomFromText('POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))', 4326);
SET @h = geography::Point(47.653, -122.358, 4326)

SELECT @g.STIntersects(@h)

如果您無法將存儲多邊形的數據類型更改為GEOGRAPHY那么您可以將輸入緯度和經度轉換為GEOMETRY並針對轉換后的值使用STContainsSTIntersects

DECLARE @PointGeography GEOGRAPHY = geography::Point(43.365267, -80.971974, 4326)
DECLARE @PointGeometry GEOMETRY = geometry::STGeomFromWKB(@PointGeography.STAsBinary(), 4326);

SELECT @PolygonGeometry.STContains(@PointGeometry);

相反的方向——試圖將GEOMETRY多邊形轉換為GEOGRPAHY很容易出錯,並且根據我的經驗可能會失敗。

請注意,如果您嘗試直接從緯度和經度值創建GEOMETRY點,那么STContains (或STIntersects )將不起作用(即,在應該匹配時不會提供匹配項)。

declare @g geometry
set @g=geometry::STGeomFromText('POLYGON((-33.229869 -70.891988, -33.251124 -70.476616, -33.703094 -70.508045, -33.693931 -70.891052,-33.229869 -70.891988))',0)

DECLARE @h geometry;

SET @h = geometry::STGeomFromText('POINT(-33.3906300 -70.5725020)', 0);
SELECT @g.STContains(@h);
  1. 你不應該混合幾何和地理。 幾何適用於平面,地理適用於球體(如地球)。
  2. 您“應該”協調 SRID 來處理這個問題。 每個 SRID(例如 2913 = NZG2000)描述一個轉換關系。 每個 SRID 都可以用來映射到/從一個統一的球體,這是你從一個球體到另一個球體的方式。
  3. 直到您在兩個值上都獲得“相同”的 SRID,許多 .STxXX 函數將返回 NULL(在這兩種情況下您可能都有默認值 0)
  4. 如果它們不一樣,但你假裝它們是一樣的,你可能會在邊緣情況下出錯。
  5. 如果您花費一些“預計算”時間,您可以確定所涉及的邊界矩形的上/左和下/右點(並存儲它們),並在索引中使用這些值來限制要檢查的記錄。 除非 AT/L < BB/R 和 AB/R > BT/L 它們不能重疊,這意味着您的 WHERE 中的簡單 4 AND 數字檢查將限制您的 STWithin 檢查

這是我在 SRID 2193 中使用的示例。 給定點半徑 3 公里內和特定學區內的所有道路

DECLARE @g geometry

SELECT @g = GEO2193 FROM dbo.schoolzones WHERE schoolID = 319

SELECT DD.full_road_name, MIN(convert(int,  dd.address_number)), MAX(convert(int,  dd.address_number))
FROM (

select A.* from dbo.[street-address] A

WHERE (((A.Shape_X - 1566027.50505) * (A.Shape_X - 1566027.50505)) + ((A.Shape_Y - 5181211.81675) * (A.Shape_Y - 5181211.81675))) < 9250000

and a.shape_y > 5181076.1943481788

and a.shape_y < 5185097.2169968253

and a.shape_x < 1568020.2202472512

and a.shape_x > 1562740.328937705

and a.geo2193.STWithin(@g) = 1
) DD
GROUP BY DD.full_road_name
ORDER BY DD.full_road_name

如果您有表(例如:SubsriberGeo),其中一列(例如:位置)將地理點作為值,並且您想從該表中找到多邊形內的所有點,這是一種方法:

 WITH polygons
 AS (SELECT 'p1' id, 
            geography::STGeomFromText('polygon ((-113.754429 52.471834 , 1 5, 5 5, -113.754429 52.471834))', 4326) poly
),
 points
 AS (SELECT [SubscriberId],[Location] as p FROM [DatabaseName].[dbo].[SubscriberGeo])
 SELECT DISTINCT 
        points.SubscriberId, 
        points.p.STAsText() as Location
 FROM polygons
      RIGHT JOIN points ON polygons.poly.STIntersects(points.p) = 1
 WHERE polygons.id IS NOT NULL;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM