web-dev-qa-db-ja.com

SQL Server 2008 Spatial:ポリゴン内のポイントを見つける

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
23
Farhan

地理学メソッド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)
29
Ben Thul

格納されたポリゴンのデータ型をGEOGRAPHYに変更できない場合は、入力緯度と経度をGEOMETRYに変換し、変換された値に対してSTContainsまたはSTIntersectsを使用できます。

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)は機能しません(つまり、必要なときに一致しません)。

2
  1. GeometryとGeographyを混在させないでください。ジオメトリはフラットプレーン用、ジオグラフィはスフェロイド(地球など)用です。
  2. これに対処するには、SRIDを「調整」する必要があります。各SRID(2913 = NZG2000など)は、変換関係を記述します。各SRIDを使用して、均一な球体との間でマッピングを行うことができます。これは、ある球体から別の球体への移動方法です。
  3. 両方の値で「同じ」SRIDに到達するまで、.STxXX関数の多くはNULLを返します(どちらの場合もデフォルトの0になる可能性があります)
  4. それらが同じではないが、同じふりをしている場合、Edgeのケースでエラーが発生する可能性があります。
  5. 「事前計算」に時間を費やす場合は、関連するバウンディング四角形の上/左および下/右のポイントを決定(および保存)し、それらの値をインデックスで使用して、チェックするレコードを制限できます。 A T/L <B B/RおよびA B/R> B T/Lが重複しない場合、つまり、WHEREでの単純な4 AND数値チェックはSTWithinチェックを制限します

SRID 2193で使用した例を次に示します。特定の地点から半径3 km以内、および特定の学校区域内のすべての道路

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
0
Roger Willcocks
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);
0
Leonel

列(例:場所)の1つに値として地理ポイントがあるテーブル(例: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;
0
grabhints