Come aggiungere la direzione e la distanza alla tabella degli attributi?


18

chiunque possa aiutare. voglio solo aggiungere la direzione (rilevamento: cioè N 25 35 E) e la distanza (lunghezza: 125 metri) come il mio nuovo campo nei dati polilinea / linea. c'è un plug-in per generare questi campi? ho provato ad usare "esporta / aggiungi colonne geometriche" nei miei dati di linea, ma è stato aggiunto solo il valore "Lunghezza".


Finora posso usare il plugin mmqgis per darmi distanza. Sto esplorando il problema della direzione.
Willy,

1
Che aspetto hanno i tuoi dati sulla polilinea? La distanza è relativamente facile da calcolare - tuttavia, il 'rilevamento' può variare sulla lunghezza di una polilinea. Stai cercando il rilevamento dal punto iniziale a quello finale ?
Simbamangu,

Sì, sto cercando di orientarmi dal punto di partenza al punto di fine ... grazie
arzandia,

1
Vuoi la distanza in linea retta dal punto iniziale al punto finale o la lunghezza della linea che segue il percorso della linea? Questi potrebbero variare notevolmente se il segmento di linea presenta curve intermedie o altri cambi di direzione.
RyanKDalton-OffTheGridMaps

Risposte:


42

È possibile calcolare il rilevamento nel Field Calculator in QGIS. Questo funziona in coordinate UTM (metriche) su piccole distanze (centinaia di km), ma sarebbe necessario qualcosa di più sofisticato per grandi distanze o per gradi decimali.

Apri la tabella degli attributi per il tuo livello di linea, attiva / disattiva la modifica e fai clic sul pulsante Field Calculator per aprire la finestra di dialogo:

inserisci qui la descrizione dell'immagine

Crea un nuovo campo come decimale con 1 o 2 precisione.

Incolla questo codice nella casella "Espressione" e fai clic su "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)))

La prima parte calcola la tangente inversa delle differenze xey e la converte in gradi (180 / pi). La seconda parte aggiunge 180 o 360 alla figura risultante per dare un rilevamento da 0 a 360 °.


2
Una soluzione molto elegante, grazie. Vorrei menzionare che se è necessario determinare il rilevamento per ciascun segmento di una polilinea, è possibile farlo suddividendo il file di forma della linea con il plug-in 'Split Feature'. Quindi caricare il nuovo shapefile (diviso) e seguire la procedura sopra descritta.
nhopton,

1
@arzandia - nota che DEVI usare QGIS 1.9 (vedi la home page per i download beta) poiché le funzioni xat () e yat () non funzionano in 1.7, che stai usando!
Simbamangu,

ho già usato la spina che hai citato. come puoi vedere l'immagine, il nome del livello è "
diviso

1
Per rispondere alla mia domanda, "Sì, puoi inserire i valori dei campi per yat (0) / yat (-1) e xat (0) / xat (-1)."
cbunn,

1
Per me ho dovuto apportare alcune modifiche allo script per farlo funzionare: (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)))
oskarlin,

21

Non hai bisogno di un plugin. Tutto è nella classe QgsPoint di PyQGIS

Se si esaminano i contenuti di una classe di punti QGIS con la funzione built-in dir di Python () in 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']

Puoi vedere che ci sono funzioni azimut e sqrDist e dopo alcuni tentativi:

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

Il problema inserisci qui la descrizione dell'immagine

Quindi nella console di 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()

ora xy contiene tutti i nodi (punti) della linea

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

Utilizzando tutti i punti del nodo della linea:

1) punto azimutale i fino al punto i + 1 (+/- 180 °) (nodi di una linea)

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) distanza euclidea tra il punto i e il punto 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
[...]

Dopo, non è molto difficile aggiungere questi valori alla tabella degli attributi.

Uso questa tecnica per analizzare i lineamenti (geologia) con matplotlib e il plugin Script Runner

inserisci qui la descrizione dell'immagine


5
+1 - Bella soluzione! Deve ... imparare ... Python ...
Simbamangu

Questa è un'ottima soluzione e super preziosa per i geologi .. ma anche così complicata
Shawn

10

La soluzione fornita da @Simbamangu è piuttosto efficace ma non copre tutti i casi. Ad esempio, l'applicazione della formula con uno spostamento orizzontale annulla il risultato, quindi è necessario utilizzare questo formulato nel calcolatore di campo di 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.