/* 2022-11-06 * * a variation on http://sedcore.eu.org/small/koch.c * check it for basic instructions */ #include #include #include typedef struct { unsigned char r, g, b; } color_t; unsigned char screen[160*90*4]; void point(int x, int y, color_t color) { y = 89 - y; screen[(y * 160 + x) * 4] = color.b; screen[(y * 160 + x) * 4 + 1] = color.g; screen[(y * 160 + x) * 4 + 2] = color.r; } int is_right(int x, int y, float x1, float y1, float x2, float y2) { float v1x = x2 - x1; float v1y = y2 - y1; float v2x = x - x1; float v2y = y - y1; float det = v1x * v2y - v2x * v1y; if (det <= 0) return 1; return 0; } void triangle(float x3, float y3, float x4, float y4, float x5, float y5) { int x, y; float xmin = x3-1; float ymin = y3-1; float xmax = x3+1; float ymax = y3+1; if (x4-1 < xmin) xmin = x4-1; if (x5-1 < xmin) xmin = x5-1; if (y4-1 < ymin) ymin = y4-1; if (y5-1 < ymin) ymin = y5-1; if (x4+1 > xmax) xmax = x4+1; if (x5+1 > xmax) xmax = x5+1; if (y4+1 > ymax) ymax = y4+1; if (y5+1 > ymax) ymax = y5+1; for (x = xmin; x <= xmax; x++) for (y = ymin; y <= ymax; y++) if (is_right(x, y, x3, y3, x4, y4) && is_right(x, y, x4, y4, x5, y5) && is_right(x, y, x5, y5, x3, y3)) point(x, y, (color_t){192, 0, 0}); } void koch(float x1, float y1, float x2, float y2, int frame) { float x3, y3; float x4, y4; float x5, y5; if (fabs(x1-x2) < .5 && fabs(y1-y2) < .5) return; x3 = x1 + (x2 - x1) / 3; y3 = y1 + (y2 - y1) / 3; x5 = x2 - (x2 - x1) / 3; y5 = y2 - (y2 - y1) / 3; x4 = x5 - x3; y4 = y5 - y3; /* cos + isin * x + iy = cos x - sin y + i sin x + cos y */ float c = 1. / 2; float s = sqrt(3) / 2; float x4n = c * x4 - s * y4; float y4n = s * x4 + c * y4; x4 = x4n + x3; y4 = y4n + y3; double angle = atan2(y2-y1, x2-x1); double length = sqrt((y2-y1)*(y2-y1) + (x2-x1)*(x2-x1)) * 2./3; float f = cos(2 * M_PI * frame / 100); float g = sin(2 * M_PI * frame*2 / 100); float x = f * length / 2; float y = g * length / 2. / 4.; c = cos(angle); s = sin(angle); float xn = c * x - s * y; float yn = s * x + c * y; x4 += xn; y4 += yn; triangle(x3, y3, x4, y4, x5, y5); koch(x1, y1, x3, y3, frame); koch(x3, y3, x4, y4, frame); koch(x4, y4, x5, y5, frame); koch(x5, y5, x2, y2, frame); } void clear(void) { unsigned char *s = screen; int i; for (i = 0; i < 160*80; i++, s+=4) { s[0] = 203; s[1] = 192; s[2] = 255; s[3] = 255; } for (i = 160*80; i < 160*90; i++, s+=4) { s[0] = 0; s[1] = 0; s[2] = 192; s[3] = 255; } } void dump(void) { fwrite(screen, 160*90*4, 1, stdout); } int main(void) { int frame = 0; while (frame < 100) { clear(); koch(0, 10, 160, 10, frame); dump(); frame++; } fflush(stdout); return 0; }