Создание равноудаленных точек в QGIS?


22

Я пытаюсь создать точки (новый слой) на определенном расстоянии вдоль дороги (существующий слой) в QGIS. Создание регулярных точек каждого метра на уровне округа с помощью ArcGIS Desktop? дает решение для ArcGIS. Как этого добиться в QGIS? Добавление точек в векторный слой точек с использованием QGIS? объясняет, как создавать точки, но ничего не делает с расстоянием.


(Я применил предложенные решения с разными мерами длин, потому что не знал преобразования). @ Решение Натанса сработало в некоторой степени, я получил ...

введите описание изображения здесь, Здесь проекция этих равноотстоящих точек отличается от исходной линии.

С предложением @ Underdark я получил

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



2
Пара моментов. Во-первых, линия должна быть в спроектированном CRS (не широта / долгота). Во-вторых, является ли ваша линия настоящей полилинией? Я не думаю, что какой-либо метод будет работать правильно на строке, содержащей строку из отдельных строк. Ник.
Ноптон

Также с моим кодом вам не нужно звонить на import locateлинию более одного раза. Просто позвоните ему один раз, и вы сможете звонить locate.pointsAlongLine(30)столько, сколько вам нужно
Натан W

Другой метод (учитывая, что Sextant, как предлагается в некоторых ответах здесь - только QGIS <2.0), также заключается в использовании плагина под названием QChainage.
Энди

Ответы:


14

Примечание: теперь есть плагин QGIS QChainage. Это делает все это и многое другое. Код ниже устарел с QGIS 2.0 и выше.

Вот некоторый код Python, который вы можете вставить в файл и использовать внутри QGIS:

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

На данный момент вам понадобится красивая библиотека Python, которую вы должны установить в любом случае, потому что она удобна в использовании. Он также имеет отличную документацию на http://toblerity.github.com/shapely/manual.html

Этот раздел я использую в следующем примере: http://toblerity.github.com/shapely/manual.html#interoperation .

Большая часть следующего кода является стандартным кодом QGIS, просто создавая функции, слои, конвертируя из wkb и wkt и обратно. Базовый бит - point = line.interpolate(currentdistance)это точка, которая возвращает точку на расстоянии вдоль линии. Мы просто закручиваем это в цикл, пока не закончим.

import qgis
from qgis.core import *
from PyQt4.QtCore import QVariant
from shapely.wkb import loads
from shapely.wkt import dumps

vl = None
pr = None

def createPointsAt(distance, geom):
    if distance > geom.length():
        print "No Way Man!"
        return

    length = geom.length()
    currentdistance = distance
    feats = []  

    while currentdistance < length: 
        line = loads(geom.asWkb())
        point = line.interpolate(currentdistance)
        fet = QgsFeature()
        fet.setAttributeMap( { 0 : currentdistance } )
        qgsgeom = QgsGeometry.fromWkt(dumps(point))
        fet.setGeometry(qgsgeom)
        feats.append(fet)
        currentdistance = currentdistance + distance

    pr.addFeatures(feats)
    vl.updateExtents()

def pointsAlongLine(distance):
    global vl
    vl = QgsVectorLayer("Point", "distance nodes", "memory")
    global pr
    pr = vl.dataProvider()  
    pr.addAttributes( [ QgsField("distance", QVariant.Int) ] )
    layer = qgis.utils.iface.mapCanvas().currentLayer()
    for feature in layer.selectedFeatures():
        geom = feature.geometry()
        createPointsAt(distance, geom)

    QgsMapLayerRegistry.instance().addMapLayer(vl)

Скопируйте и вставьте приведенный выше код в файл, я назвал мой locate.py в ~./qgis/pythonкаталоге (потому что он находится в пути Python) и просто сделаю это в консоли Python внутри QGIS.

 import locate
 locate.pointsAlongLine(30)

Это создаст новый слой точек с точками на каждые 30 метров вдоль выбранных линий, например так:

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

Примечание: код довольно грубый и может потребовать некоторой очистки.

РЕДАКТИРОВАТЬ: Самая последняя сборка QGIS теперь может делать это изначально.

Измените цикл while createPointsAtна:

 while currentdistance < length: 
    point = geom.interpolate(distance)
    fet = QgsFeature()
    fet.setAttributeMap( { 0 : currentdistance } )
    fet.setGeometry(point)
    feats.append(fet)
    currentdistance = currentdistance + distance

и вы можете удалить

from shapely.wkb import loads
from shapely.wkt import dumps

Спасибо, Натан. Я не смог получить пакет Shapely для моего питона. Я установил python 2.7, но установщик Shapely говорит, что python 2.7 отсутствует в моем реестре. Есть ли другой способ установить Shapely.
Stat-R

Я последовал за stackoverflow.com/questions/3652625/… и набрал две вышеупомянутые строки для вызова locateи использования, но все равно не получил эквидистантные очки. Кроме того, я новичок в Python, поэтому я не понимал, где запустить код (1) python в каталоге qgis или (2), что в C: \ Python27 \?
Stat-R

На какой ОС вы работаете?
Натан W

Windows 7 Professional
Stat-R

создайте файл python, C:\Users\{you user name}\.qgis\pythonзатем перезапустите QGIS, если он открыт, и перейдите к `Plugins-> Python Console . Load a line layer, select a line a call import locate` иlocate.pointsAlongLine(30)
Nathan W

5

Вы можете использовать плагин QGIS GRASS v.to.points для создания точек вдоль линий через равные промежутки времени.

# convert line to points; dmax = distance between points
v.to.points -i -v -t in=road out=road_pts type=line dmax=90

Я использовал dmax как 100, и для каждого получаются следующие прогнозы. (Я не знаю, как CRS назначается сам по себе.)CRS of Original Shape file, the line = EPSG:26915 - NAD83 / UTM zone 15N, CRS of Grass line vector obtained using v.in.ogr = EPSG:4269 - NAD83, CRS of Grass points vector obtained using v.to.points = EPSG:4326 - WGS 84
Stat-R

Теперь также так: QGIS -> Sextante -> GRASS -> v.to.points
markusN

5

Если вы хотите построить цепочку с фиксированными интервалами вдоль линии дороги, вы можете использовать плагин «Профиль из линии», чтобы сделать это. Вам нужен DEM под слоем дорожной линии, но процедура быстрая и очень простая. Ник.

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


это очень хороший и простой метод, спасибо!
Shepherdjo

2

Помните, что модель данных Shapely (Python) / GEOS (C ++) определена на плоскости. Таким образом, если ваши точки состоят из GPS-координат (широта, долгота), то при использовании этого shapely.geometry.LineString.interpolate(distance)метода будет выведена GPS-позиция на евклидовом расстоянии вдоль заданного значения LineString.

Shapely's interpolate()основан на geos::linearref::LengthIndexedLineклассе GEOS с использованием extractPointметода.

Предположительно, равномерно распределенная интерполяция в плоскости широта-долгота достаточна для приложений, рассматривающих относительно небольшие расстояния. В целом, однако, следует учитывать расстояние на сфере для приложений ГИС (как определено в WGS84 ).

Я могу придумать два обходных пути, используя модуль Shapely:

  • LineStringсвойствами являются все заданные точки и линейно интерполированные вдоль них кривые. Возможно, вы можете написать член, который обращается к интерполированным кривым и реализовать следующий линейный интеграл, заменяющий евклидово расстояние. Мне нравится этот подход, потому что, используя кусочно-непрерывную кривую, желаемые точки могут быть получены путем вычисления пересечений смежных окружностей вдоль кривой с радиусом r = radian_measure(arc_length) = arc_length / R, где R равен радиусу Земли в данной позиции.
  • закодируйте свой собственный метод интерполяции (не касаясь кода Шейпли), используя соответствующую функцию расстояния (например, формулу haversine).

Чтобы достичь этого, я хотел бы обратиться к следующему вопросу StackOverflow и, в частности, к этому ответу :

Возможно создать эквидистантные точки вдоль кривой. Но должно быть больше определения того, что вы хотите для реального ответа. Извините, но код, который я написал для этой задачи, находится в MATLAB, но я могу описать общие идеи. Есть три варианта.

Во-первых, должны ли точки быть на самом деле равноудаленными от соседей с точки зрения простого евклидова расстояния? Для этого потребуется найти пересечение в любой точке кривой с кругом фиксированного радиуса. Тогда просто шагай по кривой.

Далее, если вы намерены определить расстояние, чтобы обозначить расстояние вдоль самой кривой, если кривая является кусочно-линейной, задачу снова легко решить. Просто сделайте шаг по кривой, так как расстояние на отрезке линии легко измерить.

Наконец, если вы хотите, чтобы кривая была кубическим сплайном, опять же, это не невероятно сложно, но это немного больше работы. Здесь хитрость заключается в следующем:

  • Вычислить кусочно-линейную длину дуги от точки к точке вдоль кривой. Назовите это т. Создайте пару кубических сплайнов, x (t), y (t).

  • Дифференцируйте x и y как функции от t. Поскольку это кубические сегменты, это легко. Производные функции будут кусочно-
    квадратичными.

  • Используйте решатель оды для перемещения по кривой, интегрируя дифференциальную функцию длины дуги. В MATLAB ODE45 работал хорошо.

Таким образом, один интегрирует

sqrt((x')^2 + (y')^2)

Опять же, в MATLAB ODE45 можно установить для определения тех мест, где функция пересекает определенные заданные точки.

Если ваши навыки работы с MATLAB соответствуют поставленной задаче, вы можете посмотреть код в interparc для более подробного объяснения. Это достаточно хорошо прокомментированный код.

3 : http://www.mathworks.com/matlabcentral/fileexchange/34874-interparc


1

Sextante имеет инструмент, который может работать для вас. Sextante можно скачать из хранилища плагинов Qgis.

Ищите:
«Инструменты для линейных слоев»,
«Линии для равноотстоящих точек»


Этот плагин не доступен для QGIS 2 или 3.
Martin Burch
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.