Saya ingin fungsi untuk menghidupkan objek yang bergerak dari titik A ke titik B dari waktu ke waktu, sehingga mencapai B pada waktu tertentu, tetapi posisinya kapan saja secara acak terganggu secara terus-menerus, tetapi tidak pernah mundur. Objek bergerak sepanjang garis lurus, jadi saya hanya perlu satu dimensi.
Secara matematis, itu berarti saya mencari beberapa kontinu f (x), x ∈ [0,1], sehingga:
- f (0) = 0
- f (1) = 1
- x <y → f (x) ≤ f (y)
- Pada "sebagian besar" titik f (x + d) - f (x) tidak memiliki hubungan yang jelas dengan d. (Fungsi tidak meningkat secara seragam atau dapat diprediksi; saya pikir itu juga setara dengan mengatakan tidak ada derajat turunan yang konstan.)
Idealnya, saya sebenarnya ingin beberapa cara untuk memiliki keluarga fungsi-fungsi ini, menyediakan beberapa kondisi awal. Saya membutuhkan setidaknya 4 bit benih (16 fungsi yang mungkin), untuk penggunaan saya saat ini, tetapi karena itu tidak banyak merasa bebas untuk memberikan lebih banyak lagi.
Untuk menghindari berbagai masalah dengan akumulasi kesalahan, saya lebih suka fungsi ini tidak memerlukan kondisi internal apa pun. Artinya, saya ingin itu menjadi fungsi nyata, bukan "fungsi" pemrograman.
f'(x)>0
, sehingga integrasi normal dari nilai absolut dari setiap fungsi noise akan memenuhi semua kebutuhan Anda. Sayangnya saya tidak tahu cara mudah untuk menghitung itu, tetapi mungkin orang lain melakukannya. :)Jawaban:
Untuk posting ini, y = f (t) di mana t adalah parameter yang Anda variasikan (waktu / kemajuan) dan y adalah jarak ke target. Jadi saya akan berbicara dalam hal titik pada plot 2D di mana sumbu horizontal adalah waktu / kemajuan dan vertikal adalah jarak.
Saya pikir Anda bisa membuat kurva Bezier kubik dengan titik pertama di (0, 1) dan keempat (terakhir) titik di (1, 0). Dua titik tengah dapat ditempatkan secara acak (x = rand, y = rand) dalam kotak 1-by-1 ini. Saya tidak dapat memverifikasi ini secara analitis, tetapi hanya dari bermain-main dengan applet (yeah, silakan saja dan tertawa) tampaknya kurva Bezier tidak akan pernah berkurang dengan kendala seperti itu.
Ini akan menjadi fungsi dasar Anda b (p1, p2) yang menyediakan jalur non-menurun dari titik p1 ke titik p2.
Sekarang Anda dapat menghasilkan ab (p (1) = (0, 1), p (n) = (1, 0)) dan memilih sejumlah p (i) sepanjang kurva ini sehingga 1
Pada dasarnya, Anda membuat satu jalur "umum", dan kemudian memecahnya menjadi segmen dan meregenerasi setiap segmen.
Karena Anda menginginkan fungsi matematika: Misalkan prosedur di atas dikemas ke dalam satu fungsi y = f (t, s) yang memberi Anda jarak pada t untuk fungsi seed s. Anda akan perlu:
Jadi setiap benih harus menyediakan salah satu dari yang berikut ini:
Saya membayangkan Anda dapat mencapai salah satu dari ini dengan hanya menyediakan array angka sebagai benih. Atau, Anda bisa melakukan sesuatu seperti memasok satu angka s sebagai seed, dan kemudian memanggil generator angka acak bawaan dengan rand, rand (s + 1), rand (s + 2) dan sebagainya (atau menginisialisasi dengan s dan kemudian terus memanggil rand.NextNumber).
Perhatikan bahwa meskipun seluruh fungsi f (t, s) terdiri dari banyak segmen, Anda hanya mengevaluasi satu segmen untuk setiap t. Anda akan perlu berulang kali menghitung batas-batas segmen dengan metode ini, karena Anda akan harus menyortir mereka untuk memastikan tidak ada dua segmen tumpang tindih. Anda mungkin dapat mengoptimalkan dan menyingkirkan pekerjaan tambahan ini dan hanya menemukan titik akhir dari satu segmen untuk setiap panggilan, tetapi tidak jelas bagi saya saat ini.
Juga, kurva Bezier tidak diperlukan, spline berperilaku yang sesuai akan dilakukan.
Saya membuat contoh implementasi Matlab.
Fungsi Bezier (vektor):
Fungsi majemuk Bezier yang dijelaskan di atas (sengaja dibiarkan tidak terverifikasi untuk memperjelas berapa banyak evaluasi yang diperlukan untuk setiap panggilan):
Script yang memplot fungsi untuk seed acak (perhatikan bahwa ini adalah satu-satunya tempat di mana fungsi acak dipanggil, variabel acak ke semua kode lain disebarkan dari satu array acak ini):
Berikut ini contoh keluaran:
Tampaknya memenuhi sebagian besar kriteria Anda. Namun:
sumber
Saya kira bahwa alih-alih memadukan sekelompok cosinus yang ditransformasi (seperti yang diberikan produk titik dalam perlin noise), Anda dapat memadukan beberapa fungsi monoton yang dimulai dari f (0) = 0, seperti f (x) = x, atau 2x, atau x ^ 2, dll. Faktanya karena domain Anda terbatas pada 0 => 1, Anda juga dapat memadukan fungsi trigonometri yang sesuai dengan tagihan dalam domain tersebut seperti cos (90 * x + 270). Untuk menormalkan metode Anda hingga berakhir pada 1, Anda bisa membagi jumlah tertimbang dari metode monotonik ini mulai dari f (0) = 0 oleh f (1). Sesuatu seperti ini harusnya cukup mudah untuk dibalik juga (yang saya kumpulkan Anda inginkan dari sedikit tentang fungsi real stateless versus fungsi pemrograman).
Semoga ini membantu.
sumber
Orang dapat menganalisis gambar kasar ini. Anda dapat berakhir dengan fungsi yang menjalankan animasi Anda dengan cepat, dengan memanfaatkan fungsi rand yang seragam. Saya tahu ini bukan rumus matematika yang tepat, tetapi sebenarnya tidak ada rumus matematika untuk fungsi acak, dan bahkan jika ada, Anda akan banyak mengkode untuk mencapai ini. Mengingat Anda tidak menentukan kondisi kelancaran, profil kecepatannya adalah $ C ^ 0 $ terus menerus (tetapi karena Anda tidak berurusan dengan robot, tidak perlu khawatir tentang profil percepatan yang terputus-putus).
sumber
Cara yang biasa untuk menghasilkan urutan peningkatan angka acak N dari [0,1] adalah dengan menghasilkan angka acak N dalam rentang apa pun, kemudian membaginya semua dengan jumlah totalnya, kemudian menjumlahkannya satu per satu untuk mendapatkan urutan.
Ini dapat diperluas ke 2D dengan menghasilkan nilai-nilai ini untuk X dan Y. Anda dapat meningkatkan N untuk mendapatkan rincian yang Anda inginkan.
Dalam jawaban serupa @ teodron, Anda mengutip masalah efisiensi dengan skala waktu yang besar. Tanpa mengetahui masalah sebenarnya yang Anda hadapi, saya tidak bisa memastikan apakah kekhawatiran itu valid; tetapi opsi lain adalah menghasilkan untuk N kecil , dan hanya memperlancar hasilnya. Tergantung pada aplikasi, ini sebenarnya dapat memberikan hasil yang lebih baik .
N = 100, tidak ada smoothing
N = 15, dengan smoothing
sumber
Saya menyarankan implementasi ini terinspirasi oleh penjumlahan oktaf yang ditemukan dalam fraktal noise, dengan sedikit keledai murahan di sana-sini. Saya percaya ini cukup cepat dan dapat disetel dengan meminta oktaf lebih sedikit daripada disimpan dalam parameter dengan kehilangan presisi sekitar
1/2^octave
.Anda bisa melihatnya sebagai implementasi sedikit demi sedikit yang hanya membutuhkan waktu O (log (potongan)) . Array parameter digunakan baik untuk posisi pivot divide-and-conquer, dan untuk jarak yang ditempuh ketika mencapai pivot.
Itu bisa dibuat lebih cepat dengan pra-komputasi divisi floating point, dengan biaya menyimpan informasi tiga kali lipat.
Ini adalah contoh cepat:
Contoh diperoleh dengan kode berikut:
sumber
Berpikir keras, dan mengakui kalkulus bukanlah poin kuat saya ... apakah ini mungkin tidak mungkin? Untuk menghindari pola yang jelas, rata-rata fungsi noise atas setiap perubahan dalam x harus mendekati nol, dan untuk menjamin monotonitas, amplitudo noise dari perubahan dalam x harus lebih kecil daripada perubahan dalam x, karena amplitudo yang lebih besar dapat menghasilkan nilai yang lebih rendah pada x 'relatif terhadap x. Tapi itu berarti bahwa ketika Anda mengurangi dx ke 0, fungsi seperti itu juga harus mengurangi dA (di mana A adalah amplitudo) menuju nol, yang berarti Anda tidak mendapatkan kontribusi dari fungsi kebisingan yang sesuai.
Saya bisa membayangkan itu mungkin untuk merumuskan fungsi yang secara bertahap mengurangi kontribusi kebisingan sebagai x mendekati 1, tetapi itu akan memberi Anda fungsi melengkung yang melambat ketika x mendekati 1, yang bukan apa yang saya pikir Anda inginkan.
sumber
g(x) = 1 - f(1 - x)
, yang sebaliknya berakselerasi saat x berangkat 0.