Как добавить направление и расстояние в таблицу атрибутов?

18

Тот, кто может помочь. я просто хочу добавить направление (азимут: т.е. N 25 35 E) и расстояние (длина: 125 метров) в качестве моего нового поля в полилинии / линейных данных. есть ли плагин для генерации этих полей? Я попытался использовать «экспорт / добавить столбцы геометрии» в моих данных линии, но было добавлено только значение «Длина».

arzandia
источник
До сих пор я могу использовать плагин mmqgis для определения расстояния. Изучаю проблему направления.
Вилли
1
Как выглядят ваши полилинии? Расстояние относительно легко рассчитать, однако «длина» может меняться по всей длине ломаной. Вы ищете подшипник от начальной точки до конечной точки ?
Симбамангу
Да, я ищу направление от начальной точки до конечной точки ... спасибо
arzandia
1
Вы хотите прямолинейное расстояние от начальной точки до конечной точки или длину линии, следующей пути линии? Они могут широко варьироваться, если отрезок имеет промежуточные кривые или другие изменения направления.
RyanKDalton-OffTheGridMaps

Ответы:

42

Вы можете рассчитать направление в Калькуляторе поля в QGIS. Это работает в UTM (метрических) координатах на небольших расстояниях (сотни километров), но что-то более сложное потребуется для больших расстояний или для десятичных градусов.

Откройте таблицу атрибутов для линейного слоя, переключите редактирование и нажмите кнопку «Калькулятор поля», чтобы открыть диалоговое окно:

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

Создайте новое поле как десятичное с точностью 1 или 2.

Вставьте этот код в поле «Выражение» и нажмите «ОК»: (atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + (180 *(((yat(-1)-yat(0)) < 0) + (((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)))

Первая часть вычисляет обратный тангенс разностей x и y и преобразует его в градусы (180 / pi). Вторая часть добавляет либо 180, либо 360 к результирующей фигуре, чтобы получить угол наклона 0-360 °.

Simbamangu
источник
2
Самое элегантное решение, спасибо. Я бы сказал, что если вам нужно определить направление для каждого сегмента полилинии, вы можете сделать это, разделив шейп-файл линии с помощью плагина «Split Feature». Затем загрузите новый (разделенный) шейп-файл и выполните описанную выше процедуру.
Ноптон
1
@arzandia - обратите внимание, что вы ДОЛЖНЫ использовать QGIS 1.9 (см. домашнюю страницу для бета-загрузок), так как функции xat () и yat () не работают в 1.7, который вы используете!
Симбамангу
я уже использовал плагин в котором вы упомянули. как вы можете видеть на изображении, имя слоя «
разбито
1
Чтобы ответить на мой собственный вопрос: «Да, вы можете вставить значения полей для yat (0) / yat (-1) и xat (0) / xat (-1)».
Cbunn
1
Мне пришлось внести некоторые изменения в скрипт, чтобы заставить его работать: (atan ((xat (0) -xat (1)) / (yat (0) -yat (1)))) * 180 / 3.14159 + (180 * (((yat (0) -yat (1)) <0) + (((xat (0) -xat (1)) <0 AND (yat (0) - yat (1))> 0) * 2)))
Оскарлин
21

Вам не нужен плагин. Все в классе QgsPoint от PyQGIS

Если вы изучите содержимое класса точек QGIS с помощью встроенной функции Python dir () в консоли Python.

dir(point])
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__'
, '__getitem__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__module__', 
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'azimuth', 
'multiply', 'set', 'setX', 'setY', 'sqrDist', 'sqrDistToSegment', 'toDegreesMinutesSeconds', 'toString', 'wellKnownText', 'x', 'y']

Вы можете видеть, что есть функции азимута и sqrDist и после нескольких попыток:

- xy[0].azimuth(xy[1]) or xy[1].azimuth(xy[0]) gives the azimuth direction between two points(in degrees, +/- 180°)
- xy[0].sqrDist(xy[1]) give the square distance between two points (in the unit of the project)

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

Так в консоли Python

def select_all(layer):
     layer.select([])
     layer.setSelectedFeatures([obj.id() for obj in layer])

myline = qgis.utils.iface.activeLayer()
select_all(myline)
for elem in myline.selectedFeatures():
      xy = elem.geometry().asPolyline()

теперь xy содержит все узлы (точки) линии

# first point
print "x=%2d y=%2d" % (xy[0].x(),xy[0].y())
x=112935 y=117784
# and others...

Используя все точки узла линии:

1) азимут от точки i до точки i + 1 (+/- 180 °) (узлы линии)

for i in range(len(xy)-1):
     print "x=%2d y=%2d azim=%6.1f azim2=%6.1f" % (xy[i].x(), xy[i].y(), xy[i].azimuth(xy[i+1]), xy[i+1].azimuth(xy[i]))

x=112935 y=117784 azim= 168.4 azim2= -11.6
x=113032 y=117312 azim=-167.5 azim2=  12.5
x=112926 y=116835 azim= 177.3 azim2=  -2.7
x=112943 y=116472 azim= 145.1 azim2= -34.9
[...]

2) евклидово расстояние между точкой i и точкой i + 1

for i in range(len(xy)-1):
     print "x=%2d y=%2d dist=%6.1f" % (xy[i].x(), xy[i].y(), xy[i].sqrDist(xy[i+1]))

x=112935 y=117784 dist=232533.9
x=113032 y=117311 dist=238243.6
x=112926 y=116835 dist=131839.8
x=112943 y=116472 dist=209268.1
[...]

После этого не очень сложно добавить эти значения в таблицу атрибутов.

Я использую эту технику для анализа линеаментов (геологии) с помощью matplotlib и плагина Script Runner.

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

ген
источник
5
+1 - Отличное решение! Должен ... учиться ... Питон ...
Симбамангу
Это отличное решение и очень ценно для геологов .. но также очень сложное
Шон
10

Решение, предоставленное @Simbamangu, довольно эффективно, но не охватывает все случаи. Например, применение формулы с горизонтальным смещением приведет к ПУСТО (NULL) результату, поэтому вы должны использовать эту формулировку в Калькуляторе полей QGIS.

case
when yat(-1)-yat(0) < 0 or yat(-1)-yat(0) > 0 then 
(atan((xat(-1)-xat(0))/(yat(-1)-yat(0)))) * 180/3.14159 + 
(180 *
(((yat(-1)-yat(0)) < 0) + 
(((xat(-1)-xat(0)) < 0 AND (yat(-1) - yat(0)) >0)*2)
))
when ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) >0) then 90
when ((yat(-1)-yat(0)) = 0 and (xat(-1) - xat(0)) <0) then 270
end
Sergio
источник