The Voronoi diagram
About the code
Definition
Easy algorithm
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define NB_POINTS 20
struct SPoint
{
int x, y;
Color col;
};
int main(int argc, char* argv[])
{
SPoint points[NB_POINTS];
float radius = 1.0;
// init the window
gfx.init("Voronoi", SCREEN_WIDTH, SCREEN_HEIGHT);
gfx.init2D();
gfx.clearScreen(Color(0, 0, 0, SDL_ALPHA_OPAQUE));
// init the points
srand(time(NULL));
for (int i = 0; i < NB_POINTS; ++i)
{
points[i].x = rand() % SCREEN_WIDTH;
points[i].y = rand() % SCREEN_HEIGHT;
points[i].col = Color((rand() % 128) + 128,
(rand() % 128) + 128,
(rand() % 128) + 128);
}
Then for each point we will draw the circle. If you don't understand the formulas used to draw the circle, they are
while (sys.isQuitRequested() == false)
{
sys.processEvents();
// drawing
for (int i = 0; i < NB_POINTS; ++i)
{
// draw circles
for (float a = 0.0; a < 2.0 * M_PI; a += M_PI / 1500.0)
{
int x = points[i].x + (int)(radius * cos(a));
int y = points[i].y + (int)(radius * sin(a));
// if pixel is not out of screen
if (x >= 0 && x < SCREEN_WIDTH &&
y >= 0 && y < SCREEN_HEIGHT)
{
// if pixel is empty
if (gfx.getPixel(x, y).argb == Color(0, 0, 0, SDL_ALPHA_OPAQUE).argb)
gfx.setPixel(x, y, points[i].col);
}
}
Finally we draw the points over the circles, increase the radius and loop back.
// draw points
gfx.setPixel(points[i].x , points[i].y , Color(1, 1, 1, SDL_ALPHA_OPAQUE));
gfx.setPixel(points[i].x , points[i].y - 1, Color(1, 1, 1, SDL_ALPHA_OPAQUE));
gfx.setPixel(points[i].x , points[i].y + 1, Color(1, 1, 1, SDL_ALPHA_OPAQUE));
gfx.setPixel(points[i].x - 1, points[i].y , Color(1, 1, 1, SDL_ALPHA_OPAQUE));
gfx.setPixel(points[i].x + 1, points[i].y , Color(1, 1, 1, SDL_ALPHA_OPAQUE));
}
// increase radius
radius += 1.0;
gfx.render();
sys.wait(50);
}
Download source code
Download executable for Windows
The result looks like the image we saw before.
Thinking the other way
for (int y = 0; y < SCREEN_HEIGHT; ++y)
for (int x = 0; x < SCREEN_WIDTH; ++x)
{
Now if we follow the definition we gave at the beginning this pixel is inside the cell of one seed.
int nearest = 0;
Sint32 nearestDist = 1000000000;
for (int i = 0; i < NB_POINTS; ++i)
{
Sint32 dx = points[i].x - x;
Sint32 dy = points[i].y - y;
Sint32 dist = dx * dx + dy * dy;
if (dist < nearestDist)
{
nearest = i;
nearestDist = dist;
}
}
Now we only have to draw the pixel with the color of the nearest point.
if (sqrt(nearestDist) <= radius)
gfx.setPixel(x, y, points[nearest].col);
Download source code
Download executable for Windows
With this program, now the lines are perfectly straight.