Выравнивание нескольких точек по линии в QGIS?

11

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

В этом примере точки, ближайшие к линии на рисунке ДО, находятся в пределах 5 единиц карты от линии, в то время как крайние точки находятся на расстоянии более 10 единиц карты. Я хотел бы привязать ближайшие точки к ближайшей линии, используя допуск в 5 единиц карты для достижения результата в ПОСЛЕДНЕМ изображении.

введите описание изображения здесь

Эд Камден
источник
Таким образом, точка должна составлять 0 единиц карты в поперечном направлении от линии, но вас интересует, где точка заканчивается в продольном направлении линии относительно исходного местоположения точки?
Джо
Идеальным сценарием было бы перемещение точек по перпендикулярному пути к линии. Однако намерение состоит в том, чтобы использовать довольно небольшие допуски. Если точки перемещаются в продольном или широтном направлении по направлению к линии, это не сместит точки так сильно от предпочтительного перпендикулярного положения.
Эд Камден
Не уверен, что это лучший способ, но один из способов, который я могу придумать, - это написать некоторый код на Python для анализа двух наборов данных и получения некоторых точечных координат. Если это то, что вы хотите, то дайте мне знать, и я могу дать вам ответ. Например, для каждой точки, если абсолютное значение lat dist от линии <= 5 единиц, то боковое расстояние = 0. Вам нужно было бы импортировать библиотеку gdal, чтобы преобразовать значения x, y в координаты. См. Комментарии в: gis.stackexchange.com/questions/185445/…
Джо
С помощью PyQGIS можно создать слой памяти, в котором точки привязываются в соответствии с ранее рассмотренным допуском в 5 единиц карты и перпендикулярным путем к линии. Смотри мой ответ.
xunilk

Ответы:

15

Для этого существует (не выпущенная) версия QGIS 3.0 для этого есть встроенный инструмент. Вы можете получить ночной снимок с веб-сайта QGIS, чтобы проверить это заранее.

Сделать это:

  1. Запустить алгоритм обработки «Привязать геометрию к слою»
  2. Выберите слой точек в качестве «входного слоя»
  3. Выберите слой линии, как «опорный слой»
  4. Введите подходящий допуск (максимальное расстояние для перемещения точек во время привязки)
  5. Измените поведение на «Предпочитать ближайшую точку»

введите описание изображения здесь

Вот результат, показывающий исходные точки в виде «х», а привязанные точки в виде зеленых точек. Я использовал здесь допуск, чтобы привязывались только некоторые входные точки.

введите описание изображения здесь

ndawson
источник
Это именно то, что мне нужно. К сожалению, мой работодатель устанавливает только LTR-версии QGIS, и нам всем запрещено загружать и устанавливать тестовые версии. (вздох) Думаю, это вопрос ожидания. Это стандартная / встроенная функция или плагин?
Эд Камден
Стандартная функциональность, основанная на изменениях в классах c ++ - невозможно вручную скопировать это в более старую версию. Вы можете попробовать установить OSGEO4W на другом компьютере, а затем скопировать папку osgeo4w на USB-накопитель для запуска на рабочей станции. Мне повезло с таким подходом в прошлом.
ndawson
1
Для старой версии посмотрите на этот плагин. docs.qgis.org/2.14/en/docs/user_manual/plugins/...
Ирфан
кажется, плагин не поддерживает слои точек.
Николай Козырь
7

Это можно сделать с помощью PyQGIS . Для следующей ситуации:

введите описание изображения здесь

следующий код, учитывая допуск 5 единиц карты, был запущен на консоли Python QGIS:

from math import sqrt

registry = QgsMapLayerRegistry.instance()

points = registry.mapLayersByName('points')
line = registry.mapLayersByName('line')

feat_points = [ feat for feat in points[0].getFeatures() ]
feat_line = line[0].getFeatures().next()

new_points = []

for feat in feat_points:
    pt = feat.geometry().asPoint()
    sqrdist, point, vertex = feat_line.geometry().closestSegmentWithContext(pt)
    if sqrt(sqrdist) <= 5:
        new_points.append(point)
    else:
        new_points.append(pt)

epsg = points[0].crs().postgisSrid()

uri = "Point?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"

mem_layer = QgsVectorLayer(uri,
                           'new_points',
                           'memory')

prov = mem_layer.dataProvider()

feats = [ QgsFeature() for i in range(len(new_points)) ]

for i, feat in enumerate(feats):
    feat.setAttributes([i])
    feat.setGeometry(QgsGeometry.fromPoint(new_points[i]))

prov.addFeatures(feats)

QgsMapLayerRegistry.instance().addMapLayer(mem_layer)

Был создан слой памяти, в котором точки были привязаны в соответствии с ранее рассмотренным допуском в 5 единиц карты и перпендикулярным путем к линии.

введите описание изображения здесь

xunilk
источник
2

Вы также можете сделать это в Калькуляторе полей с помощью плагина refFunctions. Вы можете использовать Калькулятор поля для обновления геометрии слоя, а также полей. refFunctions дает вам функцию «geomdistance», чтобы найти ближайшую линию на заданном расстоянии (или «geomnearest», если вы не хотите порог), и возвращает атрибут или геометрию, а функция «closest_point» найдет ближайшую указать на заданную геометрию. Соедините их вместе, чтобы вычислить новые геометрии для вашего точечного слоя:

closest_point(geom_from_wkt(geomdistance('snap_lines','$geometry',10)) , $geometry)

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

С этим связаны некоторые ограничения: оба слоя должны быть одинаковыми CRS, а функция geomdistance выдаст ошибку, если у вас более 100 000 точек, но вы можете изменить это ограничение, если вы редактируете файл плагина refFunctions.

amcaninch
источник