SQL 服务器地理测试点是否在边界内 - STWithin() 做什么?

SQL Server geography testing if a point is within a bounds - what does STWithin() do?

我正在测试各种 SQL 地理类型方法 - 具体来说,我想了解 STContains()STWithin() 之间的区别。

根据文档:

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

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

我在微软总部周围创建了一个简单的 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

多边形声明(使用左手法则)如下,并检查是否有效:

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';

SQL Returns:

STIsValid   STIsClosed
True        True

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

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';

SQL Returns:

STContains  STIntersects    STOverlaps  STWithin
True        True            False       False

注意: 我原以为 STWithinTrue,但结果发现中心点不是 "within" 边界?

接下来,我检查SW角点是否被认为是"in"边界,如下:

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';

SQL Returns:

STContains  STIntersects    STOverlaps  STWithin
False       True            False       False

注意:在这种情况下,STContains() returns False(这是预期的),但STIntersects() returns True;如果您需要将边缘点视为 "in" 边界,则很有用。

上次测试 - 点在边界外:

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';

SQL Returns:

STContains  STIntersects    STOverlaps  STWithin
False       False           False       False

在上述所有测试中,即测试边界内、边界边缘和边界外的点,STWithin() returns False - STWithin()到returnTrue需要什么条件? (或者,STWithin() 根本不起作用吗?)

此外,在某些情况下,我希望 STOverlaps() 到 return 正确,但如果有人可以对该方法发表评论,它也会有所帮助。

如有任何建议,我们将不胜感激。

What condition is required for STWithin() to return True? (Or, does STWithin() simply not work?)

STWithin, STContains : OGC 标准方法,return 1 或 0,它们表示一个实例的所有点是否完全存在于另一个实例中。

对于您的示例,点可以存在于多边形内,但多边形不能存在于点内。将 within 视为包含的 "inverse":如果 x 在 y 之内,则 y 包含 x。 --> 如果多边形包含点,则点在多边形内:

SELECT 
@bounds.STContains( @point) AS 'bounds contains point',  --if this is true...
@point.STWithin( @bounds ) AS 'point is within bounds'; --...then this is also true

Also, I was expecting STOverlaps() to return true in some cases

这在 the documentation 中有点模糊(对于几何,但它也适用于地理):

备注 如果表示其交集的区域与实例具有相同的维度并且区域 不等于任何一个实例 .

,则两个几何实例重叠

点与多边形重叠 --> 重叠是点(==等于任一实例)--> 0。

您可以通过 "cloning" 相同的空间实例来测试它并检查它是否与自身重叠:

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 );
DECLARE @boundsclone geography=@bounds;

select @bounds.STOverlaps(@boundsclone), @boundsclone.STOverlaps(@bounds);

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

@point.STWithin( @bounds ) == @bounds.STContains( @point );

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

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

SELECT @bounds.STContains( @point) AS 'STContains', 
       @point.STWithin( @bounds ) AS 'STWithin';

Returns:

STContains  STWithin
True        True