我正在测试各种SQL地理类型的方法--特别是,我想了解以下两种方法之间的区别。STContains()
和 STWithin()
.
根据文档,如果一个地理学实例是在另一个地理学实例的空间范围内,则返回1。
StWithin()
- 如果一个地理学实例在空间上位于另一个地理学实例中,则返回1。
STContains()
- 指定调用的地理学实例是否在空间上包含了传递给该方法的地理学实例。
我在微软总部周围创建了一个简单的1公里×1公里的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
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';
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返回。
STContains STIntersects STOverlaps STWithin
True True False False
注意: 我本来以为 STWithin
将要 True
但结果发现中心点并不在 "界内"?
接下来,我检查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';
SQL返回:
STContains STIntersects STOverlaps STWithin
False True False False
注意: 在这种情况下 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';
SQL返回:
STContains STIntersects STOverlaps STWithin
False False False False
在上面所有的测试中,也就是测试一个在边界内的点,在边界边缘的点,以及在边界外的点。STWithin()
返回 False
- 需要什么条件 STWithin()
返回 True
? (或者,是否 STWithin()
根本就不行?)
另外,我还期待着 STOverlaps()
在某些情况下返回true,但如果有人能对该方法做出评论,也会有所帮助。
任何建议都将被感激。
STWithin()需要什么条件才能返回True?(或者说,STWithin()根本就不工作?)
STWithin, STContains : OGC标准方法,返回1或0,它们表示一个实例的所有点是否完全存在于另一个实例中。
对于你的例子,点可以存在于多边形内,但多边形不能存在于点内。把 within 看成是 contains 的 "反义"。如果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
另外,我希望STOverlaps()在某些情况下能返回true。
这一点有点模糊,在 文件 (适用于几何学,但也适用于地理学)。
备注如果代表两个几何体实例的交点的区域与实例具有相同的维度,并且该区域的维度与实例的维度相同,那么两个几何体实例就会重叠。不等于任何一个实例.
点与多边形重叠--> 重叠的是点(==等于任一实例)--> 0.
你可以通过 "克隆 "同一个空间实例来测试,检查它是否与自己重叠。
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';
结果是:
STContains STWithin
True True