Я несколько раз задавал этот вопрос по stackoverflow и irc между #qgis и #postgis, и я также пытался кодировать его или реализовать сам в postgis без реального ответа.
Используя программирование (наиболее предпочтительно Python), я хотел бы нарисовать линию от точечного слоя до его проекции на ближайшую линию линии или слоя многоугольника.
На данный момент большая часть моих данных представлена в форме ESRI и в формате postgis; однако я бы предпочел держаться подальше от решения postgis, так как я в основном пользователь shp + qgis.
Идеальным решением было бы реализовать GDAL / OGR с Python или подобными библиотеками.
- Использование библиотек GDAL / OGR с чего мне начать? Можно ли дать план решения?
- Могу ли я использовать NetworkX для анализа ближайшего соседа?
- Это действительно возможно?
Если это проще, точки могут соединяться с конечной точкой сегмента вместо проецируемой точки
Ответы:
Этот вопрос оказался немного сложнее, чем я думал, чтобы получить право. Существует множество реализаций самого короткого расстояния, такого как предоставленное Shapely расстояние (от GEOS). Однако лишь немногие решения обеспечивают точку пересечения, но только расстояние.
Моя первая попытка буферизовала точку на расстоянии между точкой и многоугольником и искала пересечения, но ошибки округления не дают точного ответа.
Вот полное решение с использованием Shapely, основанное на этих уравнениях :
Для потомков, похоже, что это расширение ArcView прекрасно справляется с этой проблемой, слишком плохо, что на мертвой платформе, написанной на мертвом языке ...
источник
pairs
это алгоритмически O (N) или что-то. Решение @eprand, возможно, можно изменить, чтобы использовать KNN, но мне пока удалось обойтись без PostGIS ...Ответ PostGIS (для многоканальной строки, если линейная строка, удалите функцию st_geometryn)
источник
Это немного устарело, но я искал решения этой проблемы сегодня (точка -> линия). Самое простое решение, с которым я столкнулся для этой связанной проблемы:
источник
Если я вас правильно понимаю, функциональность, о которой вы просите, встроена в PostGIS.
Чтобы получить точку, спроецированную на линию, вы можете использовать ST_Closestpoint (в PostGIS 1.5)
Некоторые советы о том, как его использовать, вы можете прочитать здесь: http://blog.jordogskog.no/2010/02/07/how-to-use-the-new-distance-related-functions-in-postgis-part1/
Например, можно найти ближайшую точку на многоугольнике к другому многоугольнику.
Если вы хотите провести линию между двумя ближайшими точками на обеих геометриях, вы можете использовать ST_Shortestline. ST_Closestpoint - это первая точка в ST_Shortestline
Длина ST_Shortestline между двумя геометриями такая же, как ST_Distance между геометриями.
источник
См. Комментарий ниже относительно того, как мой ответ не следует считать надежным решением ... Я оставлю этот оригинальный пост здесь, чтобы другие могли изучить проблему.
Если я понимаю вопрос, эта общая процедура должна работать.
Чтобы найти кратчайший путь между точкой (как определено с помощью x, y или x, y, z) и полиномом (как определено соединительным набором из x, y или x, y, z) в евклидовом пространстве:
1) Из заданной пользователем точки (я назову ее pt0) найдите ближайшую вершину полилинии (pt1). OGRinfo может опрашивать вершины полилинии, и тогда вычисления расстояния могут быть сделаны стандартными методами. Например, выполнить итерацию по расстоянию, рассчитанному как * Math.cos (ptx_radians) * Math.pow ((Math.sin ((pt0_radians-ptx_radians) / 2)), 2)))
2) Сохраните соответствующее минимальное значение расстояния (d1) и (pt1)
3) посмотрите на два сегмента, отходящих от pt1 (в подкладке ogrinfo это будут предыдущие и последующие вершины). Запишите эти вершины (n2 и n3).
4) создать формулу y = mx + b для каждого сегмента
5) Свяжите свою точку (pt0) с перпендикуляром для каждой из этих двух формул
6) Рассчитать расстояние и пересечения (d2 и d3; pt2, pt3)
7) Сравните три расстояния (d1, d2, d3) для самых коротких. Ваш pt0 для связанного узла (pt1, pt2 или pt3) является самой короткой ссылкой.
Это ответ потока сознания - надеюсь, моя ментальная картина проблемы и решения подходит.
источник
Вот скрипт на Python для QGIS> 2.0, созданный из советов и решений, приведенных выше. Он отлично работает за разумное количество точек и линий. Но я не пробовал это с огромным количеством предметов.
Конечно, его нужно было скопировать в режиме ожидания или как-нибудь еще менее «питоническое решение» и сохранить как «closest.point.py».
В наборе инструментов QGIS выберите сценарий, инструменты, добавьте сценарий и выберите его.
!!! ВНИМАНИЕ !!! Обратите внимание, что некоторые «странные» / неправильные спроецированные точки могут быть получены из-за этой команды линии:
В этом
counterSelec
значении указывается, сколько из них возвращается. Фактически каждая точка должна проецироваться на максимально короткое расстояние до каждого линейного объекта; и минимальное найденное расстояние даст правильную линию и проецируемую точку в качестве ближайших соседей, которых мы ищем. Чтобы сократить время цикла, используется ближайшая команда Neighbor. При выбореcounterSelec
значения, уменьшенного до 1, будет возвращен «первый» встреченный объект (точнее, ограничивающий прямоугольник), и он может оказаться неправильным. Объекты с разными размерами линий могут быть обязательными для выбора, могут быть 3, 5 или даже больше ближайших объектов для определения кратчайшего расстояния. Чем выше значение, тем дольше это занимает. С сотнями точек и линий он начинает очень медленно работать с 3 или 5 ближайшими соседями, с тысячами он может ошибаться с такими значениями.источник
В зависимости от ваших интересов и варианта использования может быть полезно изучить «алгоритмы сопоставления карт». Например, есть проект RoadMatcher на OSM вики: http://wiki.openstreetmap.org/wiki/Roadmatcher .
источник