Постгис - ST_within сделал не то, что я хочу. Как найти точку в полой области? - PullRequest
1 голос
/ 29 февраля 2020

См. Печать экрана.

Я выполнил пространственный запрос в Postgis, чтобы вернуть избирательный округ (область), в которой находится точка на карте. В запросе используется функция ST_within, где точка находится внутри многоугольника.

Как видно из распечатки, точка на самом деле не «в» области многоугольника York Outer, хотя технически можно сказать, что она «внутри», или, по крайней мере, Постгис так считает. Дело в том, что на самом деле в центральном Йорке.

Я уверен, что Postgis фактически возвращает оба, но так как я получаю только первую запись из курсора, это то, что я вижу.

Точка может быть только в одном избирательном округе за один раз и этот запрос вернул неправильный или, скорее, я задал неправильный вопрос о базе данных.

Какую функцию я должен использовать, чтобы гарантировать, что я всегда возвращаю правильную область для точки, где возможно, что область может иметь полый интерьер или странная форма?

ST_within allows a non overlapping point

Спасибо

Фил

Ответы [ 2 ]

3 голосов
/ 29 февраля 2020

Это должно работать так, как вы описали. Может быть, что-то не так с данными? Не могли бы вы предоставить небольшую репродукцию с данными о многоугольниках / точках?

Кроме того, несколько распространенная причина таких проблем - не действительные данные ГИС. Вы можете проверить форму многоугольника с помощью функции PostGIS ST_IsValid. Если данные недействительны, различные инструменты могут интерпретировать их по-разному, и то, как данные ГИС отрисовываются, может не соответствовать тому, что, как думает PostGIS, представляют эти данные, вызывая больше путаницы.

Вот простое повторение, показывающее, что оно работает так, как вы ожидаете, с точкой внутри только отверстия внешнего многоугольника st_within внутреннего многоугольника, а не внешнего:

select st_astext(point), name 
from 
  (select 
       'outer' as name, 
       st_geomfromtext('polygon((0 0, 30 0, 30 30, 0 30, 0 0), (10 10, 20 10, 20 20, 10 20, 10 10))') g
  union all 
  select 
      'inner' as name, 
       st_geomfromtext('polygon((10 10, 20 10, 20 20, 10 20, 10 10))') g
  ) shapes
cross join
  (select st_geomfromtext('point(15 15)') point
   union all
   select st_geomfromtext('point(5 5)') point
  ) points
where st_within(point, g)

Мои результаты

1   POINT(5 5)     outer
2   POINT(15 15)   inner
2 голосов
/ 29 февраля 2020

Учитывая ваши полигоны и запрос, как вы описали, он должен работать без проблем. Рассмотрим следующие геометрии ..

enter image description here

.. вы видите, что точка лежит только внутри внутреннего многоугольника. Если вы выполняете запрос с ST_Within, дающим координаты точки, вы должны получить только внутренний многоугольник:

WITH j (geom) AS (VALUES 
  ('POLYGON((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))'),
  ('POLYGON((26.88 31.08,30.57 31.08,30.57 28.49,26.88 28.49,26.88 31.08))'))
SELECT * FROM j
WHERE ST_Within('POINT(28.46 28.64)',j.geom)

enter image description here

Однако, если ваш запрос каким-либо образом использует BBOX полигонов вместо их области, вы действительно получите и внешние полигоны, например:

WITH j (geom) AS (VALUES 
  ('POLYGON((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))'),
  ('POLYGON((26.88 31.08,30.57 31.08,30.57 28.49,26.88 28.49,26.88 31.08))'))
SELECT * FROM j
WHERE ST_Within('POINT(28.46 28.64)',j.geom::GEOMETRY::BOX2D)

enter image description here

Попробуйте добавить образец данных и запрос к вашему вопросу. Надеюсь, это поможет вам отладить ваш код.

...