Мой первый вопрос: «Что такое случайный многоугольник?»Или, точнее, «Что такое случайный набор многоугольников?»Случайные точечные процессы довольно четко определены.Я сомневаюсь, что это относится к полигонам (хотя это действительно любопытно - поэтому для экспертов, пожалуйста, оставьте свои комментарии).
- Вы хотите, чтобы они были случайными в том смысле, что их вершины являются случайными точками?- в каком случае вы получите что-то очень зазубренное, перекрывающееся и самопересекающееся?
- Вы позволяете своим полигонам пересекаться в первую очередь?
- Вы разрешаете своим полигонам иметь отверстия,и если да, является ли это свойство случайным само по себе?
- Должны ли какие-либо другие свойства, такие как площадь, число вершин, окружность, следовать за распределениями вероятностей?
Ваше решение зависит от того, как вы ответитеэти вопросы.Я предложу тот, который относительно прост с использованием PostGIS (потому что это то, что я знаю).Следующий запрос создает полигоны Вороного из случайных точек, делает случайный выбор и объединяет результат, где это возможно.Им можно управлять с помощью двух параметров cells
и density
, которые определяют, на сколько разделов разделено пространство и какая доля этих разделов составляет ваш результат.
WITH params AS (
SELECT
(SELECT geom FROM natural_earth_countries WHERE admin = 'United States of America') AS geom,
100000 AS cells,
0.1 AS density
), voronois AS (
SELECT (ST_Dump(ST_VoronoiPolygons(ST_GeneratePoints(p.geom, p.cells), extend_to := p.geom))).geom AS geom
FROM params AS p
), voronois_select AS (
SELECT
ROW_NUMBER() OVER (ORDER BY Random()) % Round(1::NUMERIC/p.density) AS idx,
ST_Intersection(v.geom, p.geom) AS geom
FROM voronois AS v, params AS p
)
SELECT (ST_Dump(ST_Union(geom))).geom AS geom
FROM voronois_select
WHERE idx = 0
Примечание: ST_VoronoiPolygons
не делаетне масштабируется хорошо.Вам придется увеличить ОЗУ для более высоких значений cells
Примечание: я помещаю params
только в CTE, чтобы вы могли выполнять запрос в собственном (postgre) SQL без необходимости переносаэто в plpgsql (DO
или CREATE FUNCTION
).Это может быть немного медленнее в результате.
Примечание: добавьте к запросу префикс с CREATE TABLE random_polygons AS ...
, и вы получите результат в таблице, готовой для добавления в качестве слоя, например, в QGIS.
Результаты:
США с 100000 ячеек и плотностью 0,1 (10%)
США с 100000 ячеек и плотностью 0,02 (2%)
США с 1000 ячеек и плотностью 0,1 (10%)
Опять же, только один из множества способов сделать это.Но если вы хотите иметь больший контроль над формой многоугольников, используя вышеупомянутое решение, вы можете либо сделать это, манипулируя процессом базовой точки, то есть написав свой собственный ST_GeneratePoints
, чтобы точки были более кластеризованными.Или вы создаете вложенные диаграммы Вороного, причем вторая имеет гораздо большую плотность, чем первая.
Обе модификации дадут более компактные, но сложные "случайные" полигоны.