/* Hexagon pattern generator. ./hex > output.pgm https://www.redblobgames.com/grids/hexagons/more-pixel-to-hex.html */ #include #include #include #include #ifdef _WIN32 #include #include #endif #define PI 3.14159265358979323846264338327950288419716939937510 #define MIN_BLOCK_COUNT 10 #define MAX_BLOCK_COUNT 50 #define COLOR_COUNT 4 typedef struct { double x, y; } XY; typedef struct { double a, b, c, d, e, f; } Transform; /* Apply transformations to point. */ static double ApplyTransformX(XY *input, Transform *t) { return input->x * t->a + input->y * t->b + t->c; } static double ApplyTransformY(XY *input, Transform *t) { return input->x * t->d + input->y * t->e + t->f; } static XY ApplyTransform(XY *input, Transform *t) { XY output; output.x = ApplyTransformX(input, t); output.y = ApplyTransformY(input, t); return output; } /* Integer modulus that guarantees positive return value. */ static int Mod(int n, int d) { return n > 0 ? n % d : (d - (-n % d)) % d; } int main(int argc, char **argv) { int width, height, x, y, q, r, t; int colors[MAX_BLOCK_COUNT][MAX_BLOCK_COUNT]; double angle, scale; Transform grid; XY p1, p2; if( argc != 3 || (width = atoi(argv[1])) <= 0 || (height = atoi(argv[2])) <= 0 ) { return printf("%s \n", *argv); } if( width >= 0x8000 || height >= 0x8000 ) return !puts("Output size too large."); #ifdef _WIN32 setmode(STDOUT_FILENO, O_BINARY); #endif srand(time(NULL)); /* Generate transformation for scaling and rotation. */ scale = (double)rand() / RAND_MAX * (MAX_BLOCK_COUNT - MIN_BLOCK_COUNT) + MIN_BLOCK_COUNT; scale /= width > height ? width : height; angle = ((double)rand() / RAND_MAX) * 0.5 * PI; grid.a = cos(angle) * scale; grid.d = sin(angle) * scale; grid.b = -grid.d; grid.e = grid.a; grid.c = (double)rand() / RAND_MAX * 4.0; grid.f = (double)rand() / RAND_MAX * 4.0; /* Stretch in X axis to compensate for hexagonal coordinates. */ grid.a /= sqrt(3.0); grid.b /= sqrt(3.0); /* Build table of random colors. */ for(y = 0; y < MAX_BLOCK_COUNT; y++) { for(x = 0; x < MAX_BLOCK_COUNT; x++) colors[y][x] = (int)((double)rand() / (RAND_MAX + 1u) * COLOR_COUNT); } /* Render pixels. */ printf("P5\n%d %d\n255\n", width, height); for(y = 0; y < height; y++) { p1.y = y; for(x = 0; x < width; x++) { p1.x = x; p2 = ApplyTransform(&p1, &grid); t = (int)floor(p2.x + p2.y); r = (int)floor((floor(p2.y - p2.x) + t) / 3); q = (int)floor((floor(2 * p2.x + 1) + t) / 3) - r; t = colors[Mod(q, MAX_BLOCK_COUNT)][Mod(r, MAX_BLOCK_COUNT)]; fputc(t * 255 / (COLOR_COUNT - 1), stdout); } } return 0; }