Untuk aplikasi menggambar, saya menyimpan koordinat gerakan mouse ke array kemudian menggambarnya dengan lineTo. Garis yang dihasilkan tidak mulus. Bagaimana saya bisa menghasilkan kurva tunggal antara semua poin yang dikumpulkan?
Saya sudah googled tetapi saya hanya menemukan 3 fungsi untuk menggambar garis: Untuk 2 titik sampel, cukup gunakan lineTo
. Untuk 3 titik sampel quadraticCurveTo
, untuk 4 titik sampel bezierCurveTo
,.
(Saya mencoba menggambar a bezierCurveTo
untuk setiap 4 poin dalam array, tetapi ini mengarah ke ketegaran setiap 4 poin sampel, alih-alih kurva halus terus menerus.)
Bagaimana cara menulis fungsi untuk menggambar kurva halus dengan 5 titik sampel dan seterusnya?
Jawaban:
Masalah dengan menggabungkan titik-titik sampel berikutnya bersama-sama dengan fungsi tipe "curveTo" yang terpisah, adalah bahwa di mana kurva bertemu tidak mulus. Ini karena kedua kurva berbagi titik akhir tetapi dipengaruhi oleh titik kontrol yang sepenuhnya terpisah. Salah satu solusinya adalah "melengkung ke" titik tengah antara 2 titik sampel berikutnya. Bergabung dengan kurva menggunakan titik-titik interpolasi baru ini memberikan transisi yang mulus pada titik akhir (apa titik akhir untuk satu iterasi menjadi titik kontrol untuk iterasi berikutnya.) Dengan kata lain dua kurva terputus-putus memiliki lebih banyak kesamaan sekarang.
Solusi ini diekstraksi dari buku "Yayasan ActionScript 3.0 Animasi: Membuat segalanya bergerak". hal.95 - teknik rendering: membuat banyak kurva.
Catatan: solusi ini sebenarnya tidak menggambarkan masing-masing poin, yang merupakan judul pertanyaan saya (lebih tepatnya mendekati kurva melalui titik sampel tetapi tidak pernah melewati titik sampel), tetapi untuk tujuan saya (aplikasi menggambar), itu cukup baik untuk saya dan secara visual Anda tidak bisa membedakannya. Ada adalah solusi untuk pergi melalui semua titik sampel, tetapi jauh lebih rumit (lihat http://www.cartogrammar.com/blog/actionscript-curves-update/ )
Berikut ini adalah kode gambar untuk metode aproksimasi:
sumber
Agak terlambat, tapi untuk catatan.
Anda dapat mencapai garis halus dengan menggunakan kardinal splines (alias spline kanonik) untuk menggambar kurva halus yang melewati titik-titik.
Saya membuat fungsi ini untuk kanvas - ini dibagi menjadi tiga fungsi untuk meningkatkan fleksibilitas. Fungsi pembungkus utama terlihat seperti ini:
Untuk menggambar kurva memiliki sebuah array dengan x, y poin dalam urutan:
x1,y1, x2,y2, ...xn,yn
.Gunakan seperti ini:
Fungsi di atas memanggil dua sub-fungsi, satu untuk menghitung poin yang dihaluskan. Ini mengembalikan array dengan poin baru - ini adalah fungsi inti yang menghitung poin yang dihaluskan:
Dan untuk benar-benar menggambar titik sebagai kurva yang dihaluskan (atau garis tersegmentasi lainnya selama Anda memiliki x, y array):
Tampilkan cuplikan kode
Ini menghasilkan ini:
Anda dapat dengan mudah memperluas kanvas sehingga Anda dapat menyebutnya seperti ini:
Tambahkan yang berikut ke javascript:
Anda dapat menemukan versi yang lebih optimal ini di NPM (
npm i cardinal-spline-js
) atau di GitLab .sumber
ptsa
haruspts
, atau yang lain akan membuang erro.Jawaban pertama tidak akan melewati semua poin. Grafik ini akan melewati semua titik dan akan menjadi kurva yang sempurna dengan titik-titik seperti [{x:, y:}] n titik-titik tersebut.
sumber
Seperti yang ditunjukkan Daniel Howard , Rob Spencer menjelaskan apa yang Anda inginkan di http://scaledinnovation.com/analytics/splines/aboutSplines.html .
Berikut ini demo interaktif: http://jsbin.com/ApitIxo/2/
Ini dia sebagai potongan jika jsbin turun.
sumber
Saya menemukan ini berfungsi dengan baik
sumber
Saya memutuskan untuk menambahkan, daripada memposting solusi saya ke posting lain. Di bawah ini adalah solusi yang saya bangun, mungkin tidak sempurna, tetapi sejauh ini hasilnya bagus.
Penting: itu akan melewati semua poin!
Jika Anda punya ide, untuk membuatnya lebih baik , silakan bagikan kepada saya. Terima kasih.
Berikut adalah perbandingan sebelum sesudah:
Simpan kode ini ke HTML untuk mengujinya.
sumber
Cobalah KineticJS - Anda dapat menentukan Spline dengan berbagai titik. Ini sebuah contoh:
URL lama: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-spline-tutorial/
Lihat url arsip: https://web.archive.org/web/20141204030628/http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-spline-tutorial/
sumber
Sangat terlambat tetapi terilhami oleh jawaban Homan yang sangat sederhana, izinkan saya untuk mengirim solusi yang lebih umum (umum dalam arti bahwa solusi Homan crash pada array poin dengan kurang dari 3 simpul):
sumber
Untuk menambah metode splines kardinal K3N dan mungkin mengatasi kekhawatiran TJ Crowder tentang kurva 'mencelupkan' di tempat-tempat yang menyesatkan, saya memasukkan kode berikut dalam
getCurvePoints()
fungsi, tepat sebelumres.push(x);
Ini secara efektif menciptakan kotak pembatas (tidak terlihat) antara setiap pasangan poin berurutan dan memastikan kurva tetap berada dalam kotak pembatas ini - yaitu. jika suatu titik pada kurva berada di atas / di bawah / kiri / kanan dari kedua titik, itu mengubah posisinya berada di dalam kotak. Di sini titik tengah digunakan, tetapi ini bisa diperbaiki, mungkin menggunakan interpolasi linier.
sumber
Jika Anda ingin menentukan persamaan kurva melalui n poin maka kode berikut akan memberi Anda koefisien polinomial derajat n-1 dan menyimpan koefisien ini ke
coefficients[]
array (mulai dari istilah konstan). Koordinat x tidak harus berurutan. Ini adalah contoh dari polinomial Lagrange .sumber