Ідентифікація "довгих та вузьких" багатокутників у PostGIS


10

У мене є набір багатокутників, що представляють великі площі, скажімо міські квартали. Я хочу визначити великі ділянки, що перетинаються між ними.

Але є проблема: іноді ці багатокутники будуть перетинатися по периметру (тому що вони були намальовані з невеликою точністю). Це призведе до довгих і вузьких перекриттів, які мене не цікавлять.

Але в інший час будуть великі перекриття надійних багатокутників, тобто великі райони, де багатокутник мікрорайону перекривається іншим. Я хочу вибрати лише це.

Дивіться малюнок нижче лише перекриттів. Уявіть, що я хотів вибрати лише синій багатокутник у нижньому лівому куті.

перекриття

Я міг би дивитись на райони, але іноді вузькі такі довгі, що вони мають великі площі, як синій багатокутник. Я намагався скласти співвідношення площі / периметра, але це також дало неоднозначні результати.

Я навіть намагався використовувати ST_MinimumClearance, але іноді на великих ділянках буде прикріплена вузька частина, або дві дуже близькі вершини.

Будь-які ідеї інших підходів?


Зрештою, для мене найкраще було використовувати негативний буфер, як запропонували @Cyril та @FGreg нижче.

Я використовував щось на кшталт:

ST_Area(ST_Buffer(geom, -10)) as neg_buffer_area

У моєму випадку одиниці були метрами, тому 10 м негативного буфера.

Для вузьких багатокутників ця область повертала нуль (також геометрія була б порожньою). Потім я використав цей стовпчик для фільтрації вузьких багатокутників.


4
Звичайно, для цього можна використовувати співвідношення площі / периметра.
Вінс

Важко сказати, звідки на зображенні відмінні багатокутники, але робити щось подібне до цього gis.stackexchange.com/a/265233/64838 може працювати? Обчисліть мінімальний обертовий обмежувальний ящик, а потім відкиньте його з невеликою шириною або висотою.
FGreg

Ви також можете спробувати використати негативний буфер, як описано тут: Як я можу ідентифікувати дійсно тонкі багатокутники у файлі форми?
FGreg

Відповіді:


5

Я б спробував створити негативний буфер, якщо він їсть тонкі багатокутники, то це добре, якщо він не їсть багатокутник, то це мій ... :-)

запустіть цей сценарій, попередньо встановивши 2/3 ширини лінійних багатокутників ...

create table name_table as
SELECT ST_Buffer(
(ST_Dump(
(ST_Union(
ST_Buffer(
(geom),-0.0001))))).geom,
0.0001)) as geom from source_table

ОС: -) ...


врешті-решт, ваша пропозиція - це те, що найкраще працювало для мене. Я закінчив використовувати щось на кшталт ST_Area(ST_Buffer(geom, -10)), у моєму випадку - 10 -10 метрів. Якщо з цього виразу щось повернулося 0, то я міг би його відфільтрувати.
bplmp

9

Замість площі / периметра краще використовувати площу, розділену на квадрат периметра (або його зворотну).

Це також називається "індекс форми". Квадрат периметра, розділений на площу, має мінімальне значення 4 * Pi () (у випадку диска, який є найбільш компактною 2D геометрією), тому його можна нормалізувати на 4 * Pi () для легкого інтерпретація (нормалізовані значення, близькі до 1, тоді означають, що у вас дуже компактні об'єкти, а квадрати мають значення приблизно 1,27).

EDIT: Поріг на площі буде корисним для видалення дуже дрібних артефактів, які можуть бути компактними. Тоді індекс форми показав би кращий контраст. EDIT: окрім цієї відповіді, використання ST_Snap може допомогти вам вирішити проблему до того, як вона виникне.


Дякую! Але я не впевнений, як ST_Snap міг би допомогти в цьому випадку ... Якщо я правильно зрозумів, ви пропонуєте щось подібне (o.overlap_perimeter^2 / o.overlap_area) / (4 * Pi()) as overlap_ratio? Це має гірші результати для мене, ніж просто площа / периметр.
bplmp

Зараз використовую o.overlap_perimeter / (4 * sqrt(o.overlap_area)) as overlap_ratioзгідно з цим документом, але все ж гірші результати (хоча важко підрахувати, що я маю на увазі під гіршими) isprs-ann-photogramm-remote-sens-spatial-inf-sci.net/I-7/135/… , сторінка 183.
bplmp

2
Дякую за це, я ніколи не чув про "індекс форми". Я завжди думав, що використання мінімально обмежуючого прямокутника - найкращий спосіб відповісти на таке питання. Я знайшов це, repository.asu.edu/attachments/111230/content/… , що цікаво.
Джон Пауелл

@JohnPowell інтерстируючий папір, спасибі Я бачу, що те, що я знаю як індекс фігури, називається в документі індексом круглості. Моя проблема з мінімальними обмежуючими прямокутниками полягає в тому, що він не працює з дуже увігнутими предметами (наприклад, у формі U)
radouxju

@bplmp ST_Snap допоможе вам оснастити вершини "майже" сусідніх многокутників, щоб вони більше не перетиналися. На ваших фігурах немає масштабу, але ваш артефакт виглядає як лінії, тому, мабуть, ви можете використовувати театр значення допуску, щоб уникнути артефактів, але це не впливає на великі багатокутники.
radouxju

5

Одним із варіантів було б використання відношення площі багатокутника до найдовшої лінії, яку можна провести за допомогою його кінцівок. Визначення довгих вузьких багатокутників.

select * from polygons where ST_Length(ST_LongestLine(geom, geom)) < ST_Area(geom) * 4

Це досить добре працює для треугольників. Ви можете налаштувати співвідношення (на що ви помножуєте площу) відповідно до ваших потреб та проекції.


1

Здається, що це може відповідати вашому випадку використання: Усуньте вибрані багатокутники

Поєднує вибрані багатокутники вхідного шару з певними суміжними багатокутниками, стираючи їх загальну межу. Суміжний багатокутник може бути або тим, який має найбільшу або найменшу площу, або тим, що розділяє найбільшу загальну межу з багатокутником, який потрібно усунути.

Елімінація зазвичай використовується для позбавлення від косого полігонів, тобто крихітних багатокутників, які є результатом процесів перетину полігону, де межі входів схожі, але не однакові.

Здається, ви хочете спробувати варіант "Найбільший загальний кордон".


Я усвідомлюю, що ви просили постгістичні рішення, а не рішення qgis. Мої вибачення, я не думаю, що постгігієри мають аналогічну функцію, але я залишу це для нащадків.
FGreg

0

Мені це здається ідеальним випадком використання для розширення топології PostGIS . Параметр допуску топології визначає, наскільки ви дозволяєте прив'язці вершин до інших існуючих багатокутників, справлятися з низькою точністю вихідних даних та очищати їх.

Коротше кажучи, стратегія така:

1. Увімкніть розширення топології

CREATE EXTENSION postgis_topology;

2. Створіть нову порожню топологію

SELECT topology.CreateTopology('neighborhoods_topo', 4326, 1e-7);

Третій параметр - допуск, в одиницях CRS; вибирайте його розумно. В ідеалі, ви хочете мати CRS, де одиниця метрів. Якщо блок CRS не має лічильників, як у WGS 84 aka 4326, використовуйте ST_Transformдля повторного проектування полігонів.

3. Додайте стовпчик TopoGeometry до таблиці полігонів

SELECT topology.AddTopoGeometryColumn('neighborhoods_topo', 'public', 'neighborhoods', 'topogeom', 'POLYGON');

Це повертає нове layer_id. Збережіть це, воно знадобиться пізніше. Він буде шаровим, 1якщо ви почнете з нуля і збільшуватиметесь при кожному новому дзвінку.

4. Додайте всі багатокутники до топології

UPDATE public.neighborhoods
SET topogeom = topology.toTopoGeom(geom, 'neighborhoods_topo', 1, 1e-7);

Це може зайняти кілька годин для великого набору даних, будьте терплячі. 1повертається раніше слой_id.

5. Знайдіть обличчя, що з’являються у кількох районах

Знайдіть усі обличчя з топології, які присутні в 2 або більше топогеометріях. Я залишу запит як вправу. Найпростіше, мабуть, за допомогою GetTopoGeomElementsфункції, потім згрупуйте ідентифікатор обличчя і подивіться на ті, які мають кількість 2 і більше. Крім того, ви можете створити нову таблицю з очищеною геометрією зі стовпця топогеома, просто привласнивши її до стандартної геометрії topogeom::geometryта повторіть те, що у вас уже є, але тепер із чистим набором даних без накладок.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.