Bagaimana cara menambahkan Direction dan Distance ke tabel atribut?

18

siapa saja yang bisa membantu. saya hanya ingin menambahkan arah (Bantalan: yaitu N 25 35 E) dan Jarak (Panjang: 125 meter) sebagai bidang baru saya di data garis / garis. apakah ada plug-in untuk menghasilkan bidang ini? saya mencoba menggunakan "ekspor / tambahkan kolom geometri" di data baris saya, tetapi hanya nilai "Panjang" yang ditambahkan.

arzandia
sumber
Sejauh ini saya bisa menggunakan plugin mmqgis untuk memberi saya jarak. Saya menjelajahi masalah arah.
Willy
1
Seperti apa data polyline Anda? Jarak relatif mudah dihitung - namun, 'bantalan' dapat berubah sepanjang panjang polyline. Apakah Anda mencari bantalan dari titik awal ke titik akhir ?
Simbamangu
Ya, saya sedang mencari bantalan dari titik awal ke titik akhir ... terima kasih
arzandia
1
Apakah Anda ingin jarak garis lurus dari titik awal ke titik akhir, atau panjang garis mengikuti jalur garis? Ini bisa sangat bervariasi jika segmen garis memiliki kurva menengah atau perubahan arah lainnya.
RyanKDalton-OffTheGridMaps

Jawaban:

42

Anda dapat menghitung bearing dalam Field Calculator di QGIS. Ini berfungsi dalam UTM (metrik) berkoordinasi pada jarak kecil (ratusan km), tetapi sesuatu yang lebih canggih akan dibutuhkan untuk jarak besar atau untuk derajat desimal.

Buka tabel atribut untuk lapisan baris Anda, beralih pengeditan, dan klik tombol Kalkulator Bidang untuk membuka dialog:

masukkan deskripsi gambar di sini

Buat bidang baru sebagai desimal dengan presisi 1 atau 2.

Rekatkan kode ini ke kotak "Ekspresi", dan klik "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)))

Bagian pertama menghitung garis singgung terbalik dari perbedaan x dan y dan mengubahnya menjadi derajat (180 / pi). Bagian kedua menambahkan 180 atau 360 ke gambar yang dihasilkan untuk memberikan bantalan dari 0-360 °.

Simbamangu
sumber
2
Solusi paling elegan, terima kasih. Saya akan menyebutkan bahwa jika Anda perlu menentukan bantalan untuk setiap segmen dari polyline, Anda dapat melakukan ini dengan memisahkan shapefile garis dengan plug-in 'Split Feature'. Kemudian muat shapefile (split) baru dan ikuti prosedur di atas.
nhopton
1
@arzandia - perhatikan bahwa Anda HARUS menggunakan QGIS 1.9 (lihat halaman beranda untuk unduhan beta) karena fungsi xat () dan yat () tidak berfungsi di 1,7, yang Anda gunakan!
Simbamangu
saya sudah menggunakan plug-in yang telah Anda sebutkan. seperti yang Anda lihat gambarnya, nama layernya "
terpecah
1
Untuk menjawab pertanyaan saya sendiri, "Ya, Anda dapat memasukkan nilai bidang untuk yat (0) / yat (-1) dan xat (0) / xat (-1)."
cbunn
1
Bagi saya, saya harus melakukan beberapa perubahan pada skrip untuk membuatnya berfungsi: (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

Anda tidak perlu plugin. Semuanya ada di kelas QgsPoint dari PyQGIS

Jika Anda memeriksa konten kelas titik QGIS dengan fungsi dir () fungsi Python di 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']

Anda dapat melihat ada fungsi azimuth dan sqrDist dan setelah beberapa kali mencoba:

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

Masalah masukkan deskripsi gambar di sini

Jadi di konsol 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()

sekarang xy berisi semua node (titik) dari baris

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

Menggunakan semua titik simpul dari garis:

1) titik azimuth i ke titik i + 1 (+/- 180 °) (simpul garis)

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) jarak euclidean antara titik i dan titik 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
[...]

Setelah itu, tidak terlalu sulit untuk menambahkan nilai-nilai ini ke tabel atribut.

Saya menggunakan teknik ini untuk menganalisis kelurusan (geologi) dengan matplotlib dan plugin Script Runner

masukkan deskripsi gambar di sini

gen
sumber
5
+1 - Solusi yang bagus! Harus ... belajar ... Python ...
Simbamangu
Ini adalah solusi hebat dan super berharga bagi ahli geologi .. tetapi juga sangat rumit
Shawn
10

Solusi yang disediakan oleh @Simbamangu cukup efektif tetapi tidak mencakup semua kasus. Misalnya, menerapkan rumus dengan perpindahan horisontal akan NULL hasilnya, jadi Anda harus menggunakan formulasi ini dalam Field Calculator of 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
sumber