Saya punya satu set poin. Saya ingin memisahkan mereka menjadi 2 set yang berbeda. Untuk melakukan ini, saya memilih dua poin ( a dan b ) dan menggambar garis imajiner di antara mereka. Sekarang saya ingin memiliki semua poin yang tersisa dari baris ini dalam satu set dan mereka yang benar dari baris ini di set lainnya.
Bagaimana saya bisa tahu untuk titik tertentu z apakah itu di sebelah kiri atau di set yang tepat? Saya mencoba menghitung sudut antara azb - sudut yang lebih kecil dari 180 berada di sisi kanan, lebih besar dari 180 di sisi kiri - tetapi karena definisi ArcCos, sudut yang dihitung selalu lebih kecil dari 180 °. Apakah ada rumus untuk menghitung sudut lebih besar dari 180 ° (atau rumus lain untuk memilih sisi kanan atau kiri)?
sumber
Jawaban:
Gunakan tanda penentu vektor
(AB,AM)
, di manaM(X,Y)
titik kueri:Itu ada
0
di garis, dan+1
di satu sisi,-1
di sisi lain.sumber
positions
?Coba kode ini yang menggunakan produk silang :
Dimana a = garis titik 1; b = titik garis 2; c = titik untuk memeriksa.
Jika rumusnya sama dengan 0, poinnya adalah colinear.
Jika garis horizontal, maka ini mengembalikan true jika titik di atas garis.
sumber
return (b.x - a.x)*(c.y - a.y) > (b.y - a.y)*(c.x - a.x);
, tetapi kompiler mungkin mengoptimalkannya.Anda melihat tanda penentu
Ini akan menjadi positif untuk poin di satu sisi, dan negatif di sisi lain (dan nol untuk poin di garis itu sendiri).
sumber
Vektor
(y1 - y2, x2 - x1)
tegak lurus terhadap garis, dan selalu menunjuk ke kanan (atau selalu menunjuk ke kiri, jika orientasi bidang Anda berbeda dari tambang).Anda kemudian dapat menghitung titik produk dari vektor itu dan
(x3 - x1, y3 - y1)
untuk menentukan apakah titik tersebut terletak di sisi yang sama dari garis sebagai vektor tegak lurus (titik produk>0
) atau tidak.sumber
Dengan menggunakan persamaan garis ab , dapatkan koordinat x pada garis pada koordinat y yang sama dengan titik yang akan diurutkan.
sumber
Pertama periksa apakah Anda memiliki garis vertikal:
Kemudian, hitung kemiringan:
m = (y2-y1)/(x2-x1)
Kemudian, membuat persamaan garis menggunakan formulir kemiringan titik:
y - y1 = m*(x-x1) + y1
. Demi penjelasan saya, menyederhanakan ke bentuk lereng-intercept (tidak diperlukan dalam algoritma Anda):y = mx+b
.Sekarang pasang
(x3, y3)
untukx
dany
. Berikut ini beberapa pseudocode yang merinci apa yang harus terjadi:sumber
Saya menerapkan ini di java dan menjalankan tes unit (sumber di bawah). Tidak ada solusi di atas yang berfungsi. Kode ini lulus uji unit. Jika ada yang menemukan tes unit yang tidak lulus, beri tahu saya.
Kode: CATATAN:
nearlyEqual(double,double)
mengembalikan nilai true jika kedua angka tersebut sangat dekat.Inilah tes unit:
sumber
Dengan asumsi poinnya adalah (Ax, Ay) (Bx, By) dan (Cx, Cy), Anda perlu menghitung:
(Bx - Axe) * (Cy - Ay) - (By - Ay) * (Cx - Axe)
Ini akan sama dengan nol jika titik C pada garis yang dibentuk oleh titik A dan B, dan akan memiliki tanda yang berbeda tergantung pada sisi. Sisi mana ini tergantung pada orientasi koordinat (x, y) Anda, tetapi Anda dapat memasukkan nilai tes untuk A, B dan C ke dalam rumus ini untuk menentukan apakah nilai negatif berada di kiri atau ke kanan.
sumber
Saya ingin memberikan solusi yang terinspirasi oleh fisika.
Bayangkan gaya yang diterapkan di sepanjang garis dan Anda mengukur torsi gaya tentang titik tersebut. Jika torsi positif (berlawanan arah jarum jam) maka intinya adalah ke "kiri" dari garis, tetapi jika torsi negatif, titik adalah "kanan" dari garis.
Jadi jika vektor gaya sama dengan rentang dua titik yang mendefinisikan garis
Anda menguji sisi titik
(px,py)
berdasarkan tanda tes berikutsumber
pada dasarnya, saya pikir ada solusi yang jauh lebih mudah dan lurus ke depan, untuk setiap poligon yang diberikan, katakanlah terdiri dari empat simpul (p1, p2, p3, p4), temukan dua simpul yang saling berlawanan dalam poligon, di tempat lain kata-kata, temukan misalnya simpul paling kiri atas (katakanlah p1) dan simpul sebaliknya yang terletak paling kanan bawah (katakanlah). Oleh karena itu, mengingat titik pengujian Anda C (x, y), sekarang Anda harus melakukan pemeriksaan ganda antara C dan p1 dan C dan p4:
jika cx> p1x AND cy> p1y ==> berarti bahwa C lebih rendah dan ke kanan p1 berikutnya jika cx <p2x AND cy <p2y ==> berarti bahwa C adalah atas dan ke kiri dari p4
Kesimpulannya, C ada di dalam persegi panjang.
Terima kasih :)
sumber
@ AVB menjawab dalam ruby
Jika
det
positif di atas, jika negatif di bawah. Jika 0, itu di telepon.sumber
Inilah versi, lagi-lagi menggunakan logika produk silang, yang ditulis dalam Clojure.
Contoh penggunaan:
Yang mengatakan bahwa titik (0, 10) adalah di sebelah kiri garis yang ditentukan oleh (-3, -1) dan (3, 1).
CATATAN: Implementasi ini memecahkan masalah yang tidak ada yang lain (sejauh ini) lakukan! Urutan penting saat memberikan poin yang menentukan garis. Yaitu, itu adalah "jalur terarah", dalam arti tertentu. Jadi dengan kode di atas, doa ini juga menghasilkan hasil
true
:Itu karena potongan kode ini:
Akhirnya, seperti solusi berbasis produk lintas lainnya, solusi ini mengembalikan boolean, dan tidak memberikan hasil ketiga untuk collinearity. Tetapi itu akan memberikan hasil yang masuk akal, misalnya:
sumber
Cara alternatif untuk merasakan solusi yang diberikan oleh netter adalah dengan memahami sedikit implikasi geometri.
Misalkan pqr = [P, Q, R] adalah titik yang membentuk bidang yang dibagi menjadi 2 sisi dengan garis [P, R] . Kita harus mencari tahu apakah dua titik pada bidang pqr , A, B, berada di sisi yang sama.
Setiap titik T pada bidang pqr dapat direpresentasikan dengan 2 vektor: v = PQ dan u = RQ, sebagai:
T '= TQ = i * v + j * u
Sekarang implikasi geometri:
i+j: <0 0 <1 =1 >1 ---------Q------[PR]--------- <== this is PQR plane ^ pr line
Secara umum,
Signifikansi geometri lain dari i dan j (tidak terkait dengan solusi ini) adalah:
Nilai i, j dapat diperoleh dengan menyelesaikan persamaan:
Jadi kita diberi 2 poin, A, B di pesawat:
A = a1 * v + a2 * u B = b1 * v + b2 * u
Jika A, B berada di sisi yang sama, ini akan benar:
sign(a1+a2-1) = sign(b1+b2-1)
Perhatikan bahwa ini berlaku juga untuk pertanyaan: Apakah A, B di sisi yang sama dari pesawat [P, Q, R] , di mana:
T = i * P + j * Q + k * R
dan i + j + k = 1 menyiratkan bahwa T ada di pesawat [P, Q, R] dan tanda i + j + k-1 menyiratkan kedudukannya. Dari sini kita memiliki:
A = a1 * P + a2 * Q + a3 * R B = b1 * P + b2 * Q + b3 * R
dan A, B berada di sisi yang sama bidang [P, Q, R] jika
sign(a1+a2+a3-1) = sign(b1+b2+b3-1)
sumber