В настоящее время я работаю в области изохрон и базовых алгоритмов. В настоящее время возникают проблемы не в расчете самой изохроны, а в визуализации результатов.
Результатом моего изохронного алгоритма являются точки и ребра. На самом деле у меня есть работающее решение, но для 3873 ребер и для 1529 узлов все, кажется, занимает вечность (около 2,0 секунд на моем ноутбуке Lenovo T440s, который содержит процессор Core i7 2015 года и довольно быстрый SSD). Вместо секунд я хочу что-то более похожее на msec :-).
Может быть, кто-то может помочь мне сократить время расчета, необходимое для построения полигонов, которые визуализируют достижимые области.
Но подождите ... обо всем по порядку!
Вот визуализация ребер, которые я
являю результатом вычисления моей изохроны:
Эти ребра хранятся в таблице базы данных PostGIS и являются простыми линейными строками.
То, что я хочу показать пользователю, выглядит следующим образом: Обратите внимание на отключенные области на самом юге и очень востоке изображения. Они должны быть нарисованы как отдельные области (поэтому слияние не допускается :-))
В настоящее время я использую этот запрос:
SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
SELECT ST_MakePolygon(ST_ExteriorRing(ST_GeometryN(segments, generate_series(1, ST_NumGeometries(segments))))) AS polygons FROM (
SELECT ST_Union(ST_Buffer("GEOMETRY", 20, 'quad_segs=2')) AS segments FROM my_edges AS a
) AS b
) AS c
Я уже провел некоторые эксперименты и прочитал много документации, но просто не могу найти лучшего решения.
На мой взгляд, большая проблема заключается в использовании ST_Union (как указано в документации, эта функция может быть медленной). Очень интересно то, что замена его на ST_Collect, кажется, замедляет вычисление ST_Buffer, так что в целом следующий запрос занимает больше времени, хотя он не заполняет области между краями (он только создает буфер вокруг строк ):
SELECT ST_AsGeoJson(St_Transform(ST_Multi(ST_Collect(polygons)), 4326)) AS coverage FROM (
SELECT ST_Buffer(ST_Collect(ST_LineMerge("GEOMETRY")), 20, 'quad_segs=2') AS polygons FROM my_edges AS a
) AS b
Это занимает около 3,8 секунды в моей системе (так почти вдвое больше). Мой первый вывод из этого небольшого теста состоит в том, что ST_Buffer неожиданно замедляется, когда дело доходит до MultiLineStrings (даже медленнее, чем при создании буферов для каждой строки и объединении буферов - что на мой взгляд просто странно)
Я также пытался использовать альфа-формы (используя реализацию из pgRouting), но так как альфа-значение не нужно устанавливать (и на самом деле я бы сейчас не знал, какое значение установить для такого значения), я просто получил один отличный полигон ( поэтому я бы потерял регионы на самом юге и востоке как отдельные регионы, а это не то, чего я хочу).
Кроме того, ST_Polygonize (который был первым, что пришло мне в голову) не дал никаких полезных результатов, но, возможно, я что-то здесь упустил ...
Есть ли лучший способ создать область, показанную в PostGIS? Может также использовать java-код (jts) или код javascript на стороне клиента (jsts)? Фактически, я мог бы потерять некоторые детали, пока области, показанные в моем результате, остаются разделенными, и вычисление становится (намного) быстрее.
источник
Ответы:
Если оставить в стороне сериализацию GeoJSON, на моем ноутбуке примерно 6,3 секунды:
Глядя на данные в OpenJUMP, я заметил довольно мало деталей в сегментах улиц относительно желаемого уровня детализации в выходных данных. Кажется, что даже упрощение этих линий на лету может привести к значительному ускорению в PostGIS:
что снижает скорость до 2,3 секунд. Я подумал, что мог бы добиться большего успеха, сохранив обобщенную геометрию в отдельном столбце, а не вычисляя ее на лету, но это на самом деле не дало дополнительных преимуществ.
В зависимости от того, сколько кода вы готовы написать, вы почти наверняка сможете добиться большего успеха в Java, если не сказать больше, потому что вы можете использовать преимущества нескольких ядер. (Для чего стоит, JTS выполняет вышеуказанную операцию за 2,8 секунды). Одним из подходов может быть расширение,
CascadedPolygonUnion
чтобы некоторые операции объединения выполнялись параллельно. (обновление - вот ParallelCascadedPolygonUnion )В примерах данных я заметил, что ребра хранятся со ссылками на их начальный и конечный узлы, т. Е. У вас есть предварительно построенный график. Я подозреваю, что вы можете сгенерировать эти многоугольники намного быстрее, если будете работать с графиком, а не с использованием общих геометрических операций. Например, я думаю, вы могли бы так что-то вроде этого:
источник
ST_ClusterIntersecting
но я думаю, что вы все равно захотите, чтобы любая обработка графов происходила вне базы данных, так что это, вероятно, бесполезно).