SQL Server 地理测试一个点是否在边界内 - STWithin() 做什么?

bdc*_*der 5 sql-server geography

我正在测试各种 SQL 地理类型方法 - 具体来说,我想了解STContains()STWithin().

根据文档:

StWithin() - 如果地理实例在空间上位于另一个地理实例内,则返回 1;

STContains() - 指定调用 geography 实例是否在空间上包含传递给该方法的 geography 实例。

我在微软总部周围创建了一个简单的 1 km x 1 km POLYGON(实际上是一个正方形),从视觉上看,它看起来像这样:

地理边界与中心点

使用的数据点如下:

Center point: 47.6423318, -122.1391189

Polygon (Square) corner points:

SE: 47.6378402235794, -122.13244353271
NE: 47.6468233764206, -122.13244353271
NW: 47.6468233764206, -122.14577646729
SW: 47.6378402235794, -122.14577646729
Run Code Online (Sandbox Code Playgroud)

POLYGON 声明(使用左手规则)如下,并检查是否有效:

DECLARE @bounds geography;
SET @bounds = geography::STPolyFromText('POLYGON((-122.13244353271 47.6378402235794, -122.13244353271 47.6468233764206, -122.14577646729 47.6468233764206, -122.14577646729 47.6378402235794, -122.13244353271 47.6378402235794))', 4326 );

SELECT @bounds.STIsValid() AS 'STIsValid', @bounds.STIsClosed() AS 'STIsClosed';
Run Code Online (Sandbox Code Playgroud)

SQL 返回:

STIsValid   STIsClosed
True        True
Run Code Online (Sandbox Code Playgroud)

接下来,我检查中心点是否在边界内(应该是),如下

DECLARE @point geography;
SET @point = geography::Point( 47.6423318, -122.1391189, 4326 );

SELECT @bounds.STContains( @point) AS 'STContains', 
       @bounds.STIntersects( @point ) AS 'STIntersects',
       @bounds.STOverlaps( @point ) AS 'STOverlaps',
       @bounds.STWithin( @point ) AS 'STWithin';
Run Code Online (Sandbox Code Playgroud)

SQL 返回:

STContains  STIntersects    STOverlaps  STWithin
True        True            False       False
Run Code Online (Sandbox Code Playgroud)

注意:我原以为STWithinTrue,但结果中心点不在“范围内”?

接下来,我检查 SW 角点是否被视为“在”边界内,如下所示:

SET @point = geography::Point( 47.6378402235794, -122.14577646729, 4326 );

SELECT @bounds.STContains( @point) AS 'STContains', 
       @bounds.STIntersects( @point ) AS 'STIntersects',
       @bounds.STOverlaps( @point ) AS 'STOverlaps',
       @bounds.STWithin( @point ) AS 'STWithin';
Run Code Online (Sandbox Code Playgroud)

SQL 返回:

STContains  STIntersects    STOverlaps  STWithin
False       True            False       False
Run Code Online (Sandbox Code Playgroud)

注意:在这种情况下,STContains()返回False(这是预期的),但STIntersects()返回True; 如果您需要将边缘点视为“在”范围内,则很有用。

最后的测试 - 边界外的一个点:

SET @point = geography::Point( 47.647, -122.13244353271, 4326 );

SELECT @bounds.STContains( @point) AS 'STContains', 
       @bounds.STIntersects( @point ) AS 'STIntersects',
       @bounds.STOverlaps( @point ) AS 'STOverlaps',
       @bounds.STWithin( @point ) AS 'STWithin';
Run Code Online (Sandbox Code Playgroud)

SQL 返回:

STContains  STIntersects    STOverlaps  STWithin
False       False           False       False
Run Code Online (Sandbox Code Playgroud)

在上述所有的测试,就是测试了点里面的界限,在界限,内外界限的边缘,STWithin()回报False-需要什么条件STWithin()来回报True?(或者,STWithin()根本不起作用?)

另外,我希望STOverlaps()在某些情况下返回 true,但如果有人可以评论该方法,它也会有所帮助。

任何意见,将不胜感激。

bdc*_*der 1

好的,看来以下内容是正确的:

@point.STWithin( @bounds ) == @bounds.STContains( @point );
Run Code Online (Sandbox Code Playgroud)

例如,以下查询(测试中心点是否在边界内):

DECLARE @point geography;
SET @point = geography::Point( 47.6423318, -122.1391189, 4326 );

SELECT @bounds.STContains( @point) AS 'STContains', 
       @point.STWithin( @bounds ) AS 'STWithin';
Run Code Online (Sandbox Code Playgroud)

返回:

STContains  STWithin
True        True
Run Code Online (Sandbox Code Playgroud)