Menghitung jarak antara titik dan garis virtual dari dua lat / lngs

14

Silakan lihat contoh dan gambar yang sesuai.

Saya ingin mencapai berikut: menyediakan dua lokasi (lat / lng), yang ditunjukkan di bawah ini sebagai A dan B . Dari ini, garis virtual akan ditarik dan kemudian jarak antara garis ini dan C akan dihitung (dalam pengukuran apa pun).

gambar

Saya telah mencapai ini saat ini di Google Maps API v3 tetapi ingin juga dapat melakukan ini di belakang layar dalam bahasa pilihan saya. Setiap tips / ide akan sangat dihargai!

Tawanan
sumber
Apakah garis AB Great Circle ?
Kirk Kuykendall
@Kirk, Tidak, AB hanya garis lurus
Tahanan
@Michael, itu poin yang menarik. Saya harus memeriksanya!
Tahanan
@Prisoner @Kirk Secara harfiah, "garis lurus" akan lewat di bawah permukaan bumi. Secara umum, proyeksi radialnya kembali ke permukaan memang akan menjadi bagian dari lingkaran besar (menggunakan model bumi bulat).
whuber
1
@Penjara Itu adalah informasi tambahan yang sangat berguna! Ya kamu benar. Anda masih harus mengimbangi kenyataan bahwa menggunakan (lat, lon) secara berbeda mendistorsi jarak timur-barat dibandingkan dengan utara-selatan. Seperti yang disarankan oleh Jose, memproyeksikan koordinat. Ini bisa sesederhana pra-mengalikan garis bujur dengan kosinus lintang rata-rata dan kemudian berpura-pura Anda berada di pesawat Euclidean.
whuber

Jawaban:

6
def get_perp( X1, Y1, X2, Y2, X3, Y3):
    """************************************************************************************************ 
    Purpose - X1,Y1,X2,Y2 = Two points representing the ends of the line segment
              X3,Y3 = The offset point 
    'Returns - X4,Y4 = Returns the Point on the line perpendicular to the offset or None if no such
                        point exists
    '************************************************************************************************ """
    XX = X2 - X1 
    YY = Y2 - Y1 
    ShortestLength = ((XX * (X3 - X1)) + (YY * (Y3 - Y1))) / ((XX * XX) + (YY * YY)) 
    X4 = X1 + XX * ShortestLength 
    Y4 = Y1 + YY * ShortestLength
    if X4 < X2 and X4 > X1 and Y4 < Y2 and Y4 > Y1:
        return X4,Y4
    return None

Panjang terpendek adalah jarak yang Anda butuhkan, kecuali saya salah?

Berbulu
sumber
Ya, saya mencari jarak terdekat dari C ke segmen garis. Apakah ini yang dihitung matematika ini?
Tahanan
1
Itu memang bekerja dengan baik, saya melewati tiga poin (A, B, C) sebagai berikut: i.imgur.com/bK9oB.jpg dan kembali dengan lat / lng dari X. Kerja bagus!
Tahanan
1
@Hairy, Satu hal terakhir, bagaimana saya bisa memodifikasi ini untuk pergi ke titik terdekat (bukan hanya garis) jadi jika saya telah melewati titik bergabung dengan garis, bagaimana saya bisa mendapatkannya untuk memeriksa jarak ke titik?
Tahanan
1
@Hairy Awal yang baik, tetapi sepertinya terlalu sering kode ini kembali Noneketika ada solusi yang sah. Masalahnya adalah bahwa kondisi bersyarat mengasumsikan X1 <X2 dan Y1 <Y2, yang tidak selalu dapat dipastikan. Tes yang lebih baik antara keduanya diperlukan.
whuber
1
@Hairy Sepertinya pertukaran antara Anda dan @penjara ini produktif. Saya ingin menekankan bahwa saya tidak ada hubungannya dengan (atau bahkan kontrol atas) setiap perubahan dalam pemungutan suara atau poin yang mungkin terjadi dan bahwa komentar saya dimaksudkan hanya untuk membantu Anda meningkatkan balasan Anda.
whuber
11

Mungkin saya membuatnya terlalu rumit, tetapi yang Anda inginkan adalah jarak dari titik ke titik. Itu adalah jarak dari titik di sepanjang AB yang menghubungkan AB dengan C dengan garis ortogonal ke AB. Vektor ini tegak lurus terhadap AB diberikan oleh

v=[x2-x1, -(y2-y1)] # Point A is [x1,y1] Point B is [x2,y2]

(Saya telah menggunakan tanda kurung siku untuk mendefinisikan vektor, atau array dua elemen). Jarak antara C [xp, yp] dan titik A adalah

u=[x1-xp, y1-xp]

Jarak antara garis dan C hanyalah proyeksi u ke v. Jika kita menganggap mod (v) = 1 (normalisasikan saja), maka

distance = u*v = abs( (x2-x1)*(y1-yp) - (x1-xp)*(y2-y1) )

Satu-satunya komplikasi adalah Anda mungkin ingin memastikan koordinat Anda bukan pasangan lat / log WGS84, tetapi diproyeksikan (atau gunakan koordinat geodetik). Anda dapat menggunakan OGR atau Proj4 untuk ini.

Jose
sumber
3
+ beberapa juta pseudo-point karena tidak menggunakan fungsi trigonometri. Terlalu banyak orang menarik ArcTan ketika mereka harus melihat ini: en.wikipedia.org/wiki/Dot_product
Herb
@Jose, terima kasih atas jawabannya! Saya menggunakan lat / long dari google maps API. Bagian matematika cukup baru bagi saya jadi saya akan mencobanya dan melihat apa yang bisa saya hasilkan. Ada tips dengan matematika? Misalnya [x2-x1, - (y2-y1)], apa artinya?
Tahanan
Saya telah menambahkan suntingan singkat untuk ini. Pada dasarnya, ini adalah notasi array, tetapi jika Anda menyimpan koordinat Anda dalam variabel x1, x2, y1, y2 dan xp, yp, Anda hanya perlu menulis sisi kanan dari persamaan terakhir yang saya berikan. Ini cukup banyak kode C, Java, JS, Python dll yang valid :)
Jose
1
@Jose Anda menghitung jarak dari C ke garis AB. Berdasarkan gambar tersebut, saya percaya OP menginginkan jarak dari C ke segmen garis AB. Ini membutuhkan kerja ekstra untuk memeriksa apakah proyeksi C ke garis AB terletak antara A dan B atau tidak. Dalam kasus terakhir, gunakan yang lebih pendek dari dua panjang CA dan CB.
Whuber
1
@Prisoner Perbedaan utama adalah bahwa garis memanjang selamanya (hanya ditentukan oleh vektor arah dan titik, atau dengan dua titik), sedangkan segmen antara A dan B adalah bit dari garis tak terbatas yang bergerak antara A dan B (memiliki panjang yang terbatas)
Jose
4

Menjadi sedikit benci dengan semua matematika ini juga, saya akan datang dari sudut yang berbeda. Saya akan membuatnya menjadi garis 'aktual', daripada garis virtual, dan kemudian menggunakan alat yang ada.

Jika A dan B berbagi atribut, Anda dapat menghubungkannya dengan menggambar garis (Kosmo GIS memiliki alat yang akan membuat garis dari titik, dan saya percaya ada juga plugin QGIS untuk ini). Setelah Anda memiliki garis, fungsi 'dekat' pada lapisan titik 'C' akan memberi Anda jarak ke garis. Biarkan perangkat lunak menangani matematika untuk Anda!

Darren Cope
sumber
Terima kasih atas komentarnya, tetapi Hairy mendapatkan truf yang satu ini!
Tahanan
1
(+1) Anda membuat poin yang sangat baik. Algoritme komputasi geometri terkenal sulit untuk sepenuhnya benar dalam praktiknya (seperti yang dapat kita lihat dari semua kode yang ditawarkan sejauh ini, yang bermanfaat dan ilustratif tetapi belum sepenuhnya berfungsi). Menggunakan prosedur GIS tingkat tinggi seringkali merupakan cara yang baik untuk memastikan Anda mendapatkan jawaban yang Anda harapkan dan itu benar (asalkan Anda memercayai GIS Anda ;-).
whuber
1

Jika Anda menggunakan java di android, itu hanya satu baris dengan fungsi perpustakaan

import static com.google.maps.android.PolyUtil.distanceToLine;

distanceToLine:

public static double distanceToLine(LatLng p, LatLng start,LatLng end)

Menghitung jarak pada bola antara titik p dan segmen garis mulai dari akhir.

Parameter: p - titik yang akan diukur

mulai - awal segmen garis

end - akhir dari segmen garis

Pengembalian: jarak dalam meter (dengan asumsi bumi bulat)

Cukup tambahkan perpustakaan ke

dependencies {
    compile 'com.google.maps.android:android-maps-utils:0.5+'
}
indy
sumber