Misalkan Anda memiliki bidang dua dimensi dengan 2 titik (disebut a dan b) di atasnya yang diwakili oleh bilangan bulat x dan bilangan bulat ay untuk setiap titik.
Bagaimana Anda dapat menentukan jika titik c lain berada pada ruas garis yang ditentukan oleh a dan b?
Saya paling sering menggunakan python, tetapi contoh dalam bahasa apa pun akan membantu.
Jawaban:
Periksa apakah produk silang dari (ba) dan (ca) adalah 0, seperti yang dikatakan Darius Bacon, memberi tahu Anda jika titik a, b dan c sejajar.
Tetapi, karena Anda ingin mengetahui apakah c berada di antara a dan b, Anda juga harus memeriksa bahwa hasil perkalian titik dari (ba) dan (ca) positif dan lebih kecil dari kuadrat jarak antara a dan b.
Dalam pseudocode yang tidak dioptimalkan:
sumber
-epsilon < crossproduct < epsilon and min(a.x, b.x) <= c.x <= max(a.x, b.x) and min(a.y, b.y) <= c.y <= max(a.y, b.y)
sudah cukup, bukan?Inilah cara saya melakukannya:
sumber
-epsilon < (distance(a, c) + distance(c, b) - distance(a, b)) < epsilon
==
adalah hal yang salah untuk float dalam banyak kasus .math.isclose()
bisa digunakan sebagai gantinya. Tidak adamath.isclose()
di tahun 2008 dan oleh karena itu saya telah memberikan ketidaksetaraan eksplisit denganepsilon
(abs_tol
dalammath.isclose()
pembicaraan).Periksa apakah perkalian silang dari
b-a
danc-a
adalah0
: itu berarti semua titik collinear. Jika ya, periksa apakahc
koordinatnya antaraa
s danb
. Gunakan koordinat x atau y, selamaa
danb
terpisah pada sumbu tersebut (atau keduanya sama pada keduanya).Jawaban ini dulunya adalah kekacauan dari tiga pembaruan. Info berharga dari mereka: bab Brian Hayes dalam Beautiful Code mencakup ruang desain untuk fungsi uji-collinearity - latar belakang yang berguna. Jawaban Vincent membantu memperbaiki yang ini. Dan Hayes yang menyarankan pengujian hanya satu dari koordinat x atau y; awalnya kode telah
and
menggantikanif a.x != b.x else
.sumber
Berikut pendekatan lain:
Titik C (x3, y3) akan berada di antara A & B jika:
sumber
Panjang segmen tidak penting, sehingga penggunaan akar kuadrat tidak diperlukan dan harus dihindari karena kita dapat kehilangan beberapa presisi.
Beberapa contoh penggunaan acak:
sumber
==
masukis_between()
bisa gagal (btw itu adalah produk silang yang disamarkan).is_between()
:a, b = self.a, self.b
Berikut cara lain untuk melakukannya, dengan kode yang diberikan dalam C ++. Diberikan dua poin, l1 dan l2 adalah sepele untuk mengekspresikan ruas garis di antara mereka sebagai
dimana 0 <= A <= 1. Ini dikenal sebagai representasi vektor dari sebuah garis jika Anda tertarik lebih dari sekadar menggunakannya untuk soal ini. Kita dapat membagi komponen x dan y ini, memberikan:
Ambil satu titik (x, y) dan gantikan komponen x dan y menjadi dua ekspresi ini untuk menyelesaikan A. Titik tersebut berada pada garis jika solusi untuk A di kedua ekspresi adalah sama dan 0 <= A <= 1. Karena Penyelesaian untuk A membutuhkan pembagian, ada kasus khusus yang membutuhkan penanganan untuk menghentikan pembagian dengan nol ketika ruas garis horizontal atau vertikal. Solusi akhirnya adalah sebagai berikut:
sumber
Dengan menggunakan pendekatan yang lebih geometris, hitung jarak berikut:
dan uji apakah ac + bc sama dengan ab :
Itu karena ada tiga kemungkinan:
sumber
Ok, banyak penyebutan aljabar linier (perkalian vektor) dan ini bekerja dalam ruang nyata (yaitu titik kontinu atau mengambang) tetapi pertanyaannya secara khusus menyatakan bahwa kedua titik tersebut dinyatakan sebagai bilangan bulat dan dengan demikian perkalian silang tidak benar solusi meskipun dapat memberikan solusi perkiraan.
Solusi yang tepat adalah dengan menggunakan Algoritma Garis Bresenham antara dua titik dan untuk melihat apakah titik ketiga adalah salah satu titik pada garis. Jika poinnya cukup jauh sehingga menghitung algoritme tidak berkinerja baik (dan itu harus sangat besar untuk menjadi kasusnya), saya yakin Anda dapat menggali dan menemukan optimisasi.
sumber
Hasil kali skalar antara (ca) dan (ba) harus sama dengan hasil kali panjangnya (ini berarti vektor (ca) dan (ba) sejajar dan searah). Selain itu, panjang (ca) harus kurang dari atau sama dengan (ba). Pseudocode:
sumber
Saya membutuhkan ini untuk javascript untuk digunakan dalam kanvas html5 untuk mendeteksi apakah kursor pengguna berada di atas atau di dekat baris tertentu. Maka saya memodifikasi jawaban yang diberikan oleh Darius Bacon menjadi coffeescript:
sumber
Anda dapat menggunakan produk wedge dan dot:
sumber
Begini cara saya melakukannya di sekolah. Saya lupa mengapa itu bukan ide yang bagus.
EDIT:
@Darius Bacon: mengutip buku "Beautiful Code" yang berisi penjelasan mengapa kode di bawah ini bukan ide yang bagus.
sumber
Setiap titik pada ruas garis ( a , b ) (di mana a dan b adalah vektor) dapat dinyatakan sebagai kombinasi linier dari dua vektor a dan b :
Dengan kata lain, jika c terletak pada ruas garis ( a , b ):
Memecahkan m , kita dapatkan:
Jadi, pengujian kami menjadi (dengan Python):
sumber
c # Dari http://www.faqs.org/faqs/graphics/algorithms-faq/ -> Subjek 1.02: Bagaimana cara mencari jarak dari satu titik ke garis?
sumber
Berikut beberapa kode Java yang berhasil untuk saya:
sumber
bagaimana dengan memastikan bahwa kemiringannya sama dan titiknya berada di antara yang lain?
diberikan poin (x1, y1) dan (x2, y2) (dengan x2> x1) dan kandidat poin (a, b)
if (b-y1) / (a-x1) = (y2-y2) / (x2-x1) Dan x1 <a <x2
Maka (a, b) harus berada pada garis antara (x1, y1) dan (x2, y2)
sumber
Jawaban di C # menggunakan kelas Vector2D
Catat itu
adalah produk titik dari vektor segmen melalui kelebihan beban operator di C #
Kuncinya adalah mengambil keuntungan dari proyeksi titik ke garis tak hingga dan mengamati bahwa kuantitas skalar dari proyeksi memberi tahu kita secara sepele apakah proyeksi itu ada di segmen atau tidak. Kami dapat menyesuaikan batas-batas kuantitas skalar untuk menggunakan toleransi fuzzy.
Jika proyeksi dalam batas-batas kami hanya menguji apakah jarak dari titik ke proyeksi dalam batas-batas.
Manfaat dari pendekatan produk silang adalah bahwa toleransi memiliki nilai yang berarti.
sumber
Inilah solusi saya dengan C # di Unity.
sumber
Versi C # dari jawaban Jules:
sumber
Anda dapat melakukannya dengan menyelesaikan persamaan garis untuk ruas garis tersebut dengan koordinat titik. Anda akan mengetahui apakah titik itu ada di garis dan kemudian memeriksa batas-batas ruas tersebut untuk mengetahui apakah itu di dalam atau di luarnya. Anda dapat menerapkan beberapa ambang batas karena itu adalah suatu tempat di ruang yang kemungkinan besar ditentukan oleh nilai titik mengambang dan Anda tidak boleh mencapai yang tepat. Contoh di php
sumber