OK, yang ini memberi saya waktu yang sulit. Saya pikir itu cukup bagus, walaupun hasilnya tidak begitu artistik seperti yang lainnya. Itu kesepakatan dengan keacakan. Mungkin beberapa gambar menengah terlihat lebih baik, tetapi saya benar-benar ingin memiliki algoritma yang berfungsi penuh dengan diagram voronoi.
Sunting:
Ini adalah salah satu contoh dari algoritma final. Gambar pada dasarnya adalah superposisi dari tiga diagram voronoi, satu untuk setiap komponen warna (merah, hijau, biru).
Kode
ungolfed, versi komentar di akhir
unsigned short red_fn(int i, int j){
int t[64],k=0,l,e,d=2e7;srand(time(0));while(k<64){t[k]=rand()%DIM;if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)d=e,l=k;}return t[l];
}
unsigned short green_fn(int i, int j){
static int t[64];int k=0,l,e,d=2e7;while(k<64){if(!t[k])t[k]=rand()%DIM;if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)d=e,l=k;}return t[l];
}
unsigned short blue_fn(int i, int j){
static int t[64];int k=0,l,e,d=2e7;while(k<64){if(!t[k])t[k]=rand()%DIM;if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)d=e,l=k;}return t[l];
}
Butuh banyak upaya, jadi saya merasa ingin berbagi hasil pada tahap yang berbeda, dan ada yang bagus (salah) untuk ditampilkan.
Langkah pertama: minta beberapa titik ditempatkan secara acak, dengan x=y
Saya telah mengonversinya menjadi jpeg karena png asli terlalu berat untuk diunggah ( >2MB
), saya yakin itu lebih dari 50 warna abu-abu!
Kedua: memiliki koordinat y yang lebih baik
Saya tidak mampu membuat tabel koordinat lain yang dihasilkan secara acak untuk y
sumbu, jadi saya membutuhkan cara sederhana untuk mendapatkan yang " acak " dalam karakter sesedikit mungkin. Saya menggunakan x
koordinat titik lain dalam tabel, dengan melakukan bitwise AND
pada indeks titik.
Ke-3: Saya tidak ingat tapi itu semakin baik
Tetapi pada saat ini saya memiliki lebih dari 140 karakter, jadi saya perlu sedikit menurunkannya.
4: scanlines
Hanya bercanda, ini tidak diinginkan tapi agak keren, methinks.
Masih berupaya mengurangi ukuran algoritme, saya bangga mempersembahkan:
Edisi StarFox
Voronoi instagram
5: menambah jumlah poin
Saya sekarang memiliki sepotong kode yang berfungsi, jadi mari kita mulai dari 25 hingga 60 poin.
Itu sulit dilihat hanya dari satu gambar, tetapi titik-titiknya hampir semuanya berada dalam y
kisaran yang sama . Tentu saja, saya tidak mengubah operasi bitwise, &42
jauh lebih baik:
Dan di sinilah kita, pada titik yang sama dengan gambar pertama dari posting ini. Sekarang mari kita jelaskan kode untuk yang langka yang akan tertarik.
Kode tidak dijelaskan dan dijelaskan
unsigned short red_fn(int i, int j)
{
int t[64], // table of 64 points's x coordinate
k = 0, // used for loops
l, // retains the index of the nearest point
e, // for intermediary results
d = 2e7; // d is the minimum distance to the (i,j) pixel encoutnered so far
// it is initially set to 2e7=2'000'000 to be greater than the maximum distance 1024²
srand(time(0)); // seed for random based on time of run
// if the run overlaps two seconds, a split will be observed on the red diagram but that is
// the better compromise I found
while(k < 64) // for every point
{
t[k] = rand() % DIM; // assign it a random x coordinate in [0, 1023] range
// this is done at each call unfortunately because static keyword and srand(...)
// were mutually exclusive, lenght-wise
if (
(e= // assign the distance between pixel (i,j) and point of index k
_sq(i - t[k]) // first part of the euclidian distance
+
_sq(j - t[42 & k++]) // second part, but this is the trick to have "" random "" y coordinates
// instead of having another table to generate and look at, this uses the x coordinate of another point
// 42 is 101010 in binary, which is a better pattern to apply a & on; it doesn't use all the table
// I could have used 42^k to have a bijection k <-> 42^k but this creates a very visible pattern splitting the image at the diagonal
// this also post-increments k for the while loop
) < d // chekcs if the distance we just calculated is lower than the minimal one we knew
)
// { // if that is the case
d=e, // update the minimal distance
l=k; // retain the index of the point for this distance
// the comma ',' here is a trick to have multiple expressions in a single statement
// and therefore avoiding the curly braces for the if
// }
}
return t[l]; // finally, return the x coordinate of the nearest point
// wait, what ? well, the different areas around points need to have a
// "" random "" color too, and this does the trick without adding any variables
}
// The general idea is the same so I will only comment the differences from green_fn
unsigned short green_fn(int i, int j)
{
static int t[64]; // we don't need to bother a srand() call, so we can have these points
// static and generate their coordinates only once without adding too much characters
// in C++, objects with static storage are initialized to 0
// the table is therefore filled with 60 zeros
// see http://stackoverflow.com/a/201116/1119972
int k = 0, l, e, d = 2e7;
while(k<64)
{
if( !t[k] ) // this checks if the value at index k is equal to 0 or not
// the negation of 0 will cast to true, and any other number to false
t[k] = rand() % DIM; // assign it a random x coordinate
// the following is identical to red_fn
if((e=_sq(i-t[k])+_sq(j-t[42&k++]))<d)
d=e,l=k;
}
return t[l];
}
Terima kasih sudah membaca sejauh ini.