SQL Тестирование географии сервера, если точка находится в пределах границ - что делает STWithin ()? - PullRequest
1 голос
/ 02 мая 2020

Я тестирую различные SQL методы типа географии - в частности, я хочу понять разницу между STContains() и STWithin().

Согласно документам:

StWithin() - Возвращает 1, если экземпляр географии пространственно находится в другом экземпляре географии;

STContains() - Указывает, содержит ли вызывающий экземпляр географии пространственно содержащий экземпляр географии, переданный методу.

Я создал простой ПОЛИГОН размером 1 x 1 км (a на самом деле) вокруг штаб-квартиры Microsoft, визуально это выглядит так:

geography bounds with center point

Использовались следующие точки данных:

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 Возвращает:

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() ret урны 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 Возвращает:

STContains  STIntersects    STOverlaps  STWithin
False       False           False       False

Во всех вышеперечисленных тестах, то есть при проверке точки ВНУТРИ границ, КРАЯ границ и ВНЕ границ, STWithin() возвращает False - Какое условие требуется для STWithin() чтобы вернуть True? (Или STWithin() просто не работает?)

Кроме того, я ожидал, что в некоторых случаях STOverlaps() вернет true, но если кто-то может прокомментировать этот метод, это также поможет.

Любой совет будет оценен.

Ответы [ 2 ]

0 голосов
/ 11 мая 2020

Хорошо, может показаться, что верно следующее:

@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
0 голосов
/ 02 мая 2020

Какое условие требуется для STWithin () для возврата True? (Или STWithin () просто не работает?)

STWithin, STContains: OG C стандартные методы, возвращающие 1 или 0, они указывают, существуют ли ВСЕ точки одного экземпляра полностью внутри другой экземпляр.

Для вашего примера точка может существовать внутри многоугольника, но многоугольник не может существовать внутри этой точки. Представьте, что внутри «обратное» содержит: если х находится внутри у, то у содержит х. -> Если многоугольник содержит точку, то точка находится внутри многоугольника:

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);
...