Jak dodać Kierunek i Odległość do tabeli atrybutów?

18

każdy, kto może pomóc. Chcę tylko dodać kierunek (łożysko: N 25 35 E) i odległość (długość: 125 metrów) jako moje nowe pole w danych polilinii / linii. czy jest wtyczka do generowania tych pól? Próbowałem użyć opcji „eksportuj / dodaj kolumny geometrii” w moich danych linii, ale dodano tylko wartość „Długość”.

arzandia
źródło
Do tej pory mogę używać wtyczki mmqgis, aby uzyskać odległość. Badam problem z kierunkiem.
Willy,
1
Jak wyglądają twoje dane polilinii? Odległość jest stosunkowo łatwa do obliczenia - jednak „namiar” może się zmieniać na długości polilinii. Szukasz namiaru od punktu początkowego do punktu końcowego ?
Simbamangu
Tak, szukam namiaru od punktu początkowego do końcowego ... dzięki
arzandia,
1
Czy chcesz odległość w linii prostej od punktu początkowego do punktu końcowego, czy długość linii wzdłuż ścieżki linii? Mogą się one znacznie różnić, jeśli odcinek linii ma krzywe pośrednie lub inne zmiany kierunku.
RyanKDalton-OffTheGridMaps

Odpowiedzi:

42

Możesz obliczyć namiar w kalkulatorze polowym w QGIS. Działa to we współrzędnych UTM (metrycznych) na małych odległościach (setki kilometrów), ale w przypadku dużych odległości lub stopni dziesiętnych potrzebne byłoby coś bardziej zaawansowanego.

Otwórz tabelę atrybutów dla warstwy linii, przełącz edycję i kliknij przycisk Kalkulator pola, aby otworzyć okno dialogowe:

wprowadź opis zdjęcia tutaj

Utwórz nowe pole dziesiętne z dokładnością 1 lub 2.

Wklej ten kod w polu „Wyrażenie” i kliknij „OK”: (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)))

Pierwsza część oblicza odwrotną styczną do różnic xiy i konwertuje ją na stopnie (180 / pi). Druga część dodaje 180 lub 360 do uzyskanej liczby, aby uzyskać łożysko w zakresie 0-360 °.

Simbamangu
źródło
2
Najbardziej eleganckie rozwiązanie, dzięki. Wspomnę, że jeśli chcesz określić namiar dla każdego segmentu polilinii, możesz to zrobić, dzieląc plik kształtu linii za pomocą wtyczki „Podziel funkcję”. Następnie załaduj nowy (podzielony) plik kształtu i postępuj zgodnie z powyższą procedurą.
nhopton
1
@arzandia - pamiętaj, że MUSISZ używać QGIS 1.9 (patrz strona główna pobierania wersji beta), ponieważ funkcje xat () i yat () nie działają w wersji 1.7, której używasz!
Simbamangu
Użyłem już wtyczki, o której wspomniałeś. jak widać na zdjęciu, nazwa warstwy jest „podzielona” ...
arzandia
1
Aby odpowiedzieć na moje pytanie: „Tak, możesz wstawić wartości pól dla yat (0) / yat (-1) i xat (0) / xat (-1).”
cbunn,
1
Dla mnie musiałem wprowadzić pewne zmiany w skrypcie, aby działał: (atan ((xat (0) -xat (1)) / (yat (0) -yat (1)))) * 180 / 3.14159 + (180 * (((yat (0) -yat (1)) <0) + (((xat (0) -xat (1)) <0 ORAZ (yat (0) - yat (1))> 0) * 2)))
oskarlin
21

Nie potrzebujesz wtyczki. Wszystko jest w klasie QgsPoint PyQGIS

Jeśli zbadamy zawartość klasy punktowej QGIS za pomocą wbudowanej w Python funkcji dir () w konsoli Python Console.

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']

Możesz zobaczyć, że są funkcje azymutu i sqrDist i po kilku próbach:

- 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)

Problem wprowadź opis zdjęcia tutaj

Tak więc w konsoli 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()

teraz xy zawiera wszystkie węzły (punkty) linii

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

Używając wszystkich punktów węzłów linii:

1) punkt azymutu i do punktu i + 1 (+/- 180 °) (węzły linii)

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) odległość euklidesowa między punktem i a punktem 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
[...]

Następnie dodanie tych wartości do tabeli atrybutów nie jest trudne.

Używam tej techniki do analizy lineamentów (geologii) za pomocą matplotlib i wtyczki Script Runner

wprowadź opis zdjęcia tutaj

gen
źródło
5
+1 - Ładne rozwiązanie! Musisz ... nauczyć się ... Python ...
Simbamangu
To świetne rozwiązanie i bardzo cenne dla geologów .. ale także bardzo skomplikowane
Shawn
10

Rozwiązanie dostarczone przez @Simbamangu jest dość skuteczne, ale nie obejmuje wszystkich przypadków. Na przykład zastosowanie formuły z przemieszczeniem poziomym spowoduje NULL wyniku, więc należy użyć tego sformułowania w Kalkulatorze polowym 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
źródło