ST_contains не работает правильно при фильтрации - PullRequest
1 голос
/ 29 апреля 2020

У меня есть следующие таблица и данные.

create table test ( id bigserial not null,
geo geometry not null );

insert
    into
    test(geo)
values ('MULTIPOLYGON (((0 0, 0 0, 0 7, 0 7, 0 0)), ((0 0, 0 7, 7 7, 7 0, 0 0)), ((0 0, 7 0, 7 0, 0 0, 0 0)), ((7 7, 7 7, 7 0, 7 0, 7 7)), ((0 7, 0 7, 7 7, 7 7, 0 7)), ((0 0, 7 0, 7 7, 0 7, 0 0)))'),
('POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))'),
('POLYGON ((2 2, 5 2, 5 5, 2 5, 2 2))');

select * from test;

id|geo                                                                                                                                                                                        |
--|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 5|MULTIPOLYGON (((0 0, 0 0, 0 7, 0 7, 0 0)), ((0 0, 0 7, 7 7, 7 0, 0 0)), ((0 0, 7 0, 7 0, 0 0, 0 0)), ((7 7, 7 7, 7 0, 7 0, 7 7)), ((0 7, 0 7, 7 7, 7 7, 0 7)), ((0 0, 7 0, 7 7, 0 7, 0 0)))|
 6|POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))                                                                                                                                                        |
 7|POLYGON ((2 2, 5 2, 5 5, 2 5, 2 2))                                                                                                                                                        |

следующий запрос ( Q ) должен вернуть все строки

select
    *
from
    test t
where
    st_contains('MULTIPOLYGON (((0 0, 0 0, 0 7, 0 7, 0 0)), ((0 0, 0 7, 7 7, 7 0, 0 0)), ((0 0, 7 0, 7 0, 0 0, 0 0)), ((7 7, 7 7, 7 0, 7 0, 7 7)), ((0 7, 0 7, 7 7, 7 7, 0 7)), ((0 0, 7 0, 7 7, 0 7, 0 0)))',
    geo);

id|geo                                                                                                                                                                                        |
--|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
 5|MULTIPOLYGON (((0 0, 0 0, 0 7, 0 7, 0 0)), ((0 0, 0 7, 7 7, 7 0, 0 0)), ((0 0, 7 0, 7 0, 0 0, 0 0)), ((7 7, 7 7, 7 0, 7 0, 7 7)), ((0 7, 0 7, 7 7, 7 7, 0 7)), ((0 0, 7 0, 7 7, 0 7, 0 0)))|
 6|POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))                                                                                                                                                        |

Поскольку следующее ограничение возвращает true.

select
    st_contains('MULTIPOLYGON (((0 0, 0 0, 0 7, 0 7, 0 0)), ((0 0, 0 7, 7 7, 7 0, 0 0)), ((0 0, 7 0, 7 0, 0 0, 0 0)), ((7 7, 7 7, 7 0, 7 0, 7 7)), ((0 7, 0 7, 7 7, 7 7, 0 7)), ((0 0, 7 0, 7 7, 0 7, 0 0)))',
    'POLYGON ((2 2, 5 2, 5 5, 2 5, 2 2))');

Что здесь не так с запросом Q выше?

1 Ответ

1 голос
/ 29 апреля 2020

Входная геометрия недопустима, как и результат согласно do c:

Так что ST_Contains (A, B) подразумевает ST_Within (B, A ) за исключением случая неправильной геометрии, где результат всегда ложен независимо от того, определен ли он или нет.

WITH test(geo) as (
   values ('MULTIPOLYGON (((0 0, 0 0, 0 7, 0 7, 0 0)), ((0 0, 0 7, 7 7, 7 0, 0 0)), ((0 0, 7 0, 7 0, 0 0, 0 0)), ((7 7, 7 7, 7 0, 7 0, 7 7)), ((0 7, 0 7, 7 7, 7 7, 0 7)), ((0 0, 7 0, 7 7, 0 7, 0 0)))'),
  ('POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))'),
  ('POLYGON ((2 2, 5 2, 5 5, 2 5, 2 2))'))
select st_isvalid(geo), st_isvalidreason(geo) from test;

 st_isvalid |             st_isvalidreason
------------+-------------------------------------------
 f          | Too few points in geometry component[0 7]
 t          | Valid Geometry
 t          | Valid Geometry

При этом, возможно, вы захотите внимательно прочитать do c в st_contains и st_covers , поскольку существуют тонкости, когда геометрии имеют общий край.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...