Bagaimana cara mendapatkan titik terdekat pada linestring ke titik tertentu?

28

Saya telah menggunakan PostGIS untuk waktu yang lama sekarang tetapi tidak pernah harus menggunakan LINESTRINGgeometri ...! :)

Inilah yang ingin saya lakukan: Saya memiliki tabel linestrings (mewakili jalan-jalan kota tertentu, SRID 3395) dan saya ingin mencari linestrings terdekat ke titik tertentu (posisi GPS, SRID 4326).

Solusi yang saya temukan adalah memilih semua linestrings dalam poin saya menggunakan expand()metode dan menentukan jarak antara setiap linestring dan poin saya menggunakan ST_Distance()metode.

Inilah SQL:

SELECT myLineId, myLineName, ST_Distance(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395),myLineGeom) AS myLineDistance
FROM myLines
WHERE myLineGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)
ORDER BY myLineDistance;

Hasil yang saya dapatkan terlihat OK tetapi saya merasa ada sesuatu yang salah dalam implementasi saya.

1) Apakah kalian pikir expand()bisa mendapatkan semua linestrings yang bersangkutan?

2) Apakah kalian pikir ST_Distance()metode yang tepat untuk digunakan? Saya kira saya melakukan kesalahan karena jarak yang ingin saya dapatkan adalah jarak terkecil antara titik dan garis saya dan bukan jarak antara titik dan salah satu titik linestring.

Ilustrasi:

teks alternatif

Vivi
sumber

Jawaban:

11

iklan 1) Melihat dokumentasi untuk fungsi-fungsi yang digunakan, saya akan mengatakan: "Ya, semua linestrings yang bersangkutan akan ditemukan."

perluas (geometri, apung)

Fungsi ini mengembalikan kotak pembatas yang diperluas ke semua arah dari kotak pembatas dari geometri input, dengan jumlah yang ditentukan dalam argumen kedua. Sangat berguna untuk kueri jarak (), untuk menambahkan filter indeks ke kueri.

A && B

Operator "&&" adalah operator "tumpang tindih". Jika kotak pembatas A tumpang tindih dengan kotak pembatas B, operator mengembalikan true.

iklan 2) Anda harus dapat mencapai apa yang Anda inginkan melalui:

line_interpolate_point(linestring, line_locate_point(LineString, Point))

line_interpolate_point (linestring, lokasi)

Menginterpolasi titik di sepanjang garis. Argumen pertama harus berupa LINESTRING. Argumen kedua adalah float8 antara 0 dan 1 yang mewakili fraksi dari total panjang 2d, titik harus ditempatkan.

line_locate_point (LineString, Point)

Mengembalikan float antara 0 dan 1 yang mewakili lokasi titik terdekat pada LineString ke Point yang diberikan, sebagai bagian dari total panjang garis 2d. Anda dapat menggunakan lokasi yang dikembalikan untuk mengekstrak sebuah Point (line_interpolate_point)

Sumber: http://main.merlin.com.ua/doc/postgis/docs/ch06.html

underdark
sumber
Untuk poin 2), saya hanya ingin tahu apakah ST_Distance antara geometri TITIK dan geometri LINESTRING memberikan jarak sekecil mungkin antara tesis (alias panjang garis tegak lurus antara TITIK dan LINGESTRING); saya ingin jarak dari setiap geometri LINESTRING :)
Vivi
Dan saya kira itu bukan jarak yang saya cari karena "fungsi line_locate_point memberi Anda nilai antara 0 dan 1 yang mewakili lokasi titik terdekat pada LineString ke Point yang diberikan": /
Vivi
Saya khawatir Anda kehilangan saya dalam komentar terakhir Anda. Sekarang saya tidak yakin lagi apa yang Anda inginkan;)
underdark
1
Maaf :) Saya ingin ini: memberikan geometri LINESTRING (mewakili jalur) dan geometri TITIK, saya ingin memiliki geometri TITIK terdekat yang ada di jalur (yang mungkin bukan titik definisi geometri LINESTRING). Apakah sudah jelas? Mungkin saya harus memperbarui posting saya dengan gambar: D
Vivi
Saya tidak dapat memperbarui posting saya jadi inilah tautan ke gambar yang ingin saya dapatkan: i.imgur.com/UwPxo.jpg
Vivi
7

Halo

Pertama pertanyaan tentang apa yang mengembalikan ST_Distance. ST_Distance mengembalikan jarak terpendek antara garis dan titik (atau apa jenis geometri yang dimasukkan) Itu berarti bahwa ST_Distance antara titik (1 3) dan linestring (0 0,0 10) akan kembali 1. Jarak tidak akan diukur antara titik dan (0 0) atau titik dan (0 10) tetapi dari titik (1 3) hingga (0 3).

Jadi dari apa yang saya mengerti, ST_Distance memberi Anda jawaban yang Anda inginkan.

Jika Anda ingin menemukan titik (0 3) pada contoh di atas, Anda dapat menggunakan ST_Closestpoint jika Anda memiliki PostGIS 1.5. Sebagai contoh, Anda menggunakannya seperti ini: ST_Closestpoint ('LINESTRING (0 0,0 10)' :: geometry, ' POINT (1 3) ':: geometry) maka Anda harus mendapatkan poin (0 3) sebagai imbalannya, titik pada garis yang paling dekat dengan titik Anda.

HTH Nicklas

Nicklas Avén
sumber
5

Saya menemukannya :) (Yah saya kira: P)

Menggunakan ST_Line_Locate_Point()dan ST_Line_Interpolate_point()saya berhasil mendapatkan titik yang BUKAN bagian dari definisi LINESTRING tetapi IS pada baris tersebut :) Yang harus saya lakukan adalah mendapatkan jarak dari titik saya ke titik ini dan saya sudah selesai.

SELECT AsText(ST_Line_Interpolate_Point(myLineGeom,ST_Line_Locate_Point(myLineGeom,ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395))))
FROM myLines
WHERE myGeom && expand(ST_Transform(GeomFromText('POINT(LON LAT)',4326),3395), 100)

The ST_Line_Locate_Point()Metode menemukan lokasi titik terdekat pada garis ke titik tertentu, ST_Line_Interpolate_Pointmetode mengubah lokasi ini menjadi titik.

Vivi
sumber
1
St_distance antara titik dan garis akan memberi Anda jawaban yang sama. Mengapa Anda berpikir bahwa Anda harus melakukannya dengan cara ini?
Nicklas Avén
1
Saya pikir ST_Distance dapat digunakan dengan semua jenis geometri. postgis.refractions.net/docs/ST_Distance.html :ST_Distance(geometry g1, geometry g2)
Magno C
2

Utas arsip Postgis ini dapat menjawab Anda http://postgis.refractions.net/pipermail/postgis-users/2007-June/016045.html

ThomasG77
sumber
refractions.net tidak berfungsi untuk saya: "refractions.net kedaluwarsa pada 14/09/2010 dan sedang menunggu perpanjangan atau penghapusan."
underdark
@underdark berfungsi untukku
dassouki
@dassouki: itu aneh: |
underdark
@underdark refractions.net kembali berfungsi
ThomasG77