Saya sedang mengerjakan permainan yang mengharuskan pemain untuk menggambar garis dari titik A (x1, y1) ke titik B lainnya (x2, y2) di layar perangkat Android.
Saya ingin menemukan seberapa baik gambar itu cocok untuk garis lurus. Sebagai contoh, hasil dari 90% akan berarti gambar hampir cocok dengan garis. Jika pemain menggambar garis melengkung dari A ke B, itu harus mendapatkan skor rendah.
Poin akhir tidak diketahui sebelumnya. Bagaimana saya bisa melakukan ini?
j=1
sehingga Anda dapat membandingkantouchList[j]
dengantouchList[j-1]
, tetapi ketikatouch.phase == TouchPhase.Began
atautouch.phase == TouchPhase.Ended
posisi tidak ditambahkan ketouchList
dan kemudian tidak termasuk dalamsumLength
. Bug ini akan hadir dalam semua kasus tetapi akan lebih jelas ketika garis memiliki beberapa segmen.Jawaban:
Garis lurus sempurna juga akan menjadi garis terpendek yang mungkin dengan panjang total
sqrt((x1-x2)² + (y1-y2)²)
. Jalur yang lebih scribbly akan menjadi koneksi yang kurang ideal dan karenanya akan lebih lama.Saat Anda mengambil semua titik individual dari jalur yang digambar pengguna dan menjumlahkan jarak di antara mereka, Anda dapat membandingkan total panjang dengan panjang ideal. Semakin kecil total panjang dibagi dengan panjang ideal, semakin baik garis.
Ini visualisasi. Ketika titik-titik hitam adalah titik-akhir dari gerakan dan titik-titik biru adalah titik-titik yang Anda ukur selama gerakan, Anda akan menghitung dan menjumlahkan panjang garis-garis hijau dan membaginya dengan panjang garis merah:
Skor atau indeks sinuositas 1 akan sempurna, apa pun yang lebih tinggi akan kurang sempurna, apa pun di bawah 1 akan menjadi bug. Ketika Anda memilih untuk mendapatkan skor dalam persen, bagilah 100% dengan jumlah itu.
sumber
Ini mungkin bukan cara terbaik untuk mengimplementasikan ini, tetapi saya menyarankan RMSD (root mean square deviation) bisa lebih baik, daripada hanya metode jarak, dalam kasus yang disebutkan oleh Dancrumb (lihat dua baris pertama di bawah).
RMSD = sqrt(mean(deviation^2))
catatan:
=sum(abs(deviation))
)(Maafkan kualitas gambar saya yang rendah)
Seperti yang Anda lihat, Anda harus melakukannya
Jika garis Anda mengarah ke yang
(1, 3)
Anda inginkan(3, -1)
(masing-masing melalui titik asal)h
dari garis ideal ke garis pengguna, sejajar dengan vektor itu.sumber
Jawaban yang ada tidak memperhitungkan bahwa titik akhir arbitrer (daripada diberikan). Jadi, ketika mengukur kelurusan kurva, tidak masuk akal untuk menggunakan titik akhir (misalnya, untuk menghitung panjang, sudut, posisi yang diharapkan). Contoh sederhana akan menjadi garis lurus dengan kedua ujungnya kincked. Jika kita mengukur dengan menggunakan jarak dari kurva dan garis lurus antara titik-titik akhir ini akan cukup besar, karena garis lurus yang kita gambar diimbangi dari garis lurus antara titik-titik akhir.
Bagaimana kita tahu seberapa lurus kurva itu? Dengan asumsi kurva cukup halus, kami ingin tahu berapa banyak, rata-rata, garis singgung kurva berubah. Untuk garis, ini akan menjadi nol (karena garis singgung adalah konstan).
Jika kita membiarkan posisi pada waktu t menjadi (x (t), y (t)), maka garis singgung adalah (Dx (t), Dy (t)), di mana Dx (t) adalah turunan dari x pada waktu t (situs ini tampaknya tidak memiliki dukungan TeX). Jika kurva tidak diparameterisasi oleh panjang busur, kita dinormalisasi dengan membaginya dengan || (Dx (t), Dy (t)) ||. Jadi kita memiliki vektor satuan (atau sudut) dari garis singgung ke kurva pada waktu t. Jadi, sudutnya adalah a (t) = (Dx (t), Dy (t)) / || (Dx (t), Dy (t)) ||
Kami kemudian tertarik pada || Da (t) || ^ 2 yang terintegrasi di sepanjang kurva.
Mengingat bahwa kemungkinan besar kita memiliki titik data diskrit daripada kurva, kita harus menggunakan perbedaan hingga untuk memperkirakan turunannya. Jadi, Da (t) menjadi
(a(t+h)-a(t))/h
. Dan, a (t) menjadi((x(t+h)-x(t))/h,(y(t+h)-y(t))/h)/||((x(t+h)-x(t))/h,(y(t+h)-y(t))/h)||
. Kemudian kita mendapatkan S dengan menjumlahkanh||Da(t)||^2
semua titik data dan mungkin menormalkan dengan panjang kurva. Kemungkinan besar, kami menggunakanh=1
, tetapi itu benar-benar hanya faktor skala yang sewenang-wenang.Untuk mengulangi, S akan menjadi nol untuk suatu garis dan semakin besar semakin menyimpang dari suatu garis. Untuk mengonversi ke format yang diperlukan, gunakan
1/(1+S)
. Mengingat bahwa skala agak arbitrer, dimungkinkan untuk mengalikan S dengan beberapa angka positif (atau mengubahnya dengan cara lain, misalnya menggunakan bS ^ c bukan S) untuk menyesuaikan seberapa lurus kurva tertentu.sumber
Ini adalah sistem berbasis grid, kan? Temukan poin Anda sendiri untuk garis dan hitung kemiringan garis. Sekarang, dengan menggunakan perhitungan itu, tentukan poin-poin valid yang akan dilewati garis, dengan memberikan margin kesalahan dari nilai yang tepat.
Melalui pengujian coba-coba dalam jumlah singkat, tentukan jumlah pencocokan baik dan buruk apa yang akan ada dan atur permainan Anda menggunakan skala untuk hasil yang sama dari pengujian Anda.
yaitu, sebuah garis pendek dengan kemiringan hampir horizontal mungkin memiliki 7 poin yang dapat Anda tarik. Jika Anda dapat secara konsisten mencocokkan 6 atau lebih dari 7 yang ditentukan sebagai bagian dari garis lurus, maka itu akan menjadi skor tertinggi. Grading untuk panjang dan akurasi harus menjadi bagian dari penilaian.
sumber
Ukuran yang sangat mudah dan intuitif adalah area antara garis lurus pas terbaik dan kurva aktual. Menentukan ini cukup mudah:
sumber
Idenya adalah untuk menjaga semua titik yang disentuh pengguna, lalu mengevaluasi dan menjumlahkan jarak antara masing-masing titik ke garis yang terbentuk saat pengguna melepaskan layar.
Ini adalah sesuatu untuk Anda mulai dengan pseudo-code:
Apa yang
cumulativeDistance
bisa memberi Anda ide tentang pemasangan. Jarak 0 berarti pengguna berada di garis lurus sepanjang waktu. Sekarang Anda harus melakukan beberapa tes untuk melihat bagaimana berperilaku dalam konteks Anda. Dan Anda mungkin ingin memperbesar nilai yang dikembalikandistanceOfPointToLine
dengan mengkuadratkannya untuk menghukum lebih jauh jarak yang jauh dari garis.Saya tidak akrab dengan persatuan, tetapi kode di
update
sini mungkin memilikionDrag
fungsi.Dan Anda mungkin ingin menambahkan suatu tempat di sana beberapa kode untuk mencegah mendaftarkan suatu titik jika itu sama dengan yang terakhir terdaftar. Anda tidak ingin mendaftarkan barang ketika pengguna tidak bergerak.
sumber
Salah satu metode yang dapat Anda gunakan adalah dengan membagi garis menjadi segmen dan melakukan produk titik vektor antara masing-masing vektor yang mewakili segmen dan vektor yang mewakili garis lurus antara titik pertama dan terakhir. Ini memiliki manfaat membiarkan Anda menemukan segmen yang sangat "runcing" dengan mudah.
Edit:
Juga, saya akan mempertimbangkan untuk menggunakan panjang segmen selain produk titik. Vektor yang sangat pendek tetapi ortogonal harus menghitung kurang dari yang panjang yang memiliki sedikit penyimpangan.
sumber
Cara termudah dan tercepat mungkin hanya untuk mengetahui seberapa tebal garis harus mencakup semua poin dari garis yang dibuat pengguna.
Semakin tebal garis harus, semakin buruk pengguna dalam menggambar garis mereka.
sumber
Entah bagaimana mengacu pada Jawaban MSalters, berikut adalah beberapa informasi yang lebih spesifik.
Gunakan metode kuadrat terkecil agar sesuai dengan garis untuk poin Anda. Anda pada dasarnya mencari fungsi y = f (x) yang paling cocok. Setelah memilikinya, Anda dapat menggunakan nilai y aktual untuk menjumlahkan kuadrat perbedaan:
s = jumlah over ((yf (x)) ^ 2)
Semakin kecil jumlahnya, semakin lurus garisnya.
Cara mendapatkan perkiraan terbaik, dijelaskan di sini: http://math.mit.edu/~gs/linearalgebra/ila0403.pdf
Cukup baca dari "Pas garis lurus". Perhatikan bahwa t digunakan sebagai ganti x dan b bukan y. C dan D ditentukan sebagai perkiraan, maka Anda memiliki f (x) = C + Dx
Catatan Tambahan: Jelas, Anda juga harus mempertimbangkan panjang garis. Setiap baris yang terdiri dari 2 Poin akan sempurna. Saya tidak tahu konteks pastinya, tapi saya rasa saya akan menggunakan jumlah kuadrat dibagi dengan jumlah poin sebagai peringkat. Saya juga akan menambahkan persyaratan panjang minimal, jumlah minimal poin. (Mungkin sekitar 75% dari panjang maksimal)
sumber