Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
129
Task/Dragon-curve/C/dragon-curve.c
Normal file
129
Task/Dragon-curve/C/dragon-curve.c
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* x, y: coordinates of current point; dx, dy: direction of movement.
|
||||
* Think turtle graphics. They are divided by scale, so as to keep
|
||||
* very small coords/increments without losing precission. clen is
|
||||
* the path length travelled, which should equal to scale at the end
|
||||
* of the curve.
|
||||
*/
|
||||
long long x, y, dx, dy, scale, clen;
|
||||
typedef struct { double r, g, b; } rgb;
|
||||
rgb ** pix;
|
||||
|
||||
/* for every depth increase, rotate 45 degrees and scale up by sqrt(2)
|
||||
* Note how coords can still be represented by integers.
|
||||
*/
|
||||
void sc_up()
|
||||
{
|
||||
long long tmp = dx - dy; dy = dx + dy; dx = tmp;
|
||||
scale *= 2; x *= 2; y *= 2;
|
||||
}
|
||||
|
||||
/* Hue changes from 0 to 360 degrees over entire length of path; Value
|
||||
* oscillates along the path to give some contrast between segments
|
||||
* close to each other spatially. RGB derived from HSV gets *added*
|
||||
* to each pixel reached; they'll be dealt with later.
|
||||
*/
|
||||
void h_rgb(long long x, long long y)
|
||||
{
|
||||
rgb *p = &pix[y][x];
|
||||
|
||||
# define SAT 1
|
||||
double h = 6.0 * clen / scale;
|
||||
double VAL = 1 - (cos(3.141592653579 * 64 * clen / scale) - 1) / 4;
|
||||
double c = SAT * VAL;
|
||||
double X = c * (1 - fabs(fmod(h, 2) - 1));
|
||||
|
||||
switch((int)h) {
|
||||
case 0: p->r += c; p->g += X; return;
|
||||
case 1: p->r += X; p->g += c; return;
|
||||
case 2: p->g += c; p->b += X; return;
|
||||
case 3: p->g += X; p->b += c; return;
|
||||
case 4: p->r += X; p->b += c; return;
|
||||
default:
|
||||
p->r += c; p->b += X;
|
||||
}
|
||||
}
|
||||
|
||||
/* string rewriting. No need to keep the string itself, just execute
|
||||
* its instruction recursively.
|
||||
*/
|
||||
void iter_string(const char * str, int d)
|
||||
{
|
||||
long tmp;
|
||||
# define LEFT tmp = -dy; dy = dx; dx = tmp
|
||||
# define RIGHT tmp = dy; dy = -dx; dx = tmp
|
||||
while (*str != '\0') {
|
||||
switch(*(str++)) {
|
||||
case 'X': if (d) iter_string("X+YF+", d - 1); continue;
|
||||
case 'Y': if (d) iter_string("-FX-Y", d - 1); continue;
|
||||
case '+': RIGHT; continue;
|
||||
case '-': LEFT; continue;
|
||||
case 'F':
|
||||
/* draw: increment path length; add color; move. Here
|
||||
* is why the code does not allow user to choose arbitrary
|
||||
* image size: if it's not a power of two, aliasing will
|
||||
* occur and grid-like bright or dark lines will result
|
||||
* when normalized later. It can be gotten rid of, but that
|
||||
* involves computing multiplicative order and would be a huge
|
||||
* bore.
|
||||
*/
|
||||
clen ++;
|
||||
h_rgb(x/scale, y/scale);
|
||||
x += dx; y += dy;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dragon(long leng, int depth)
|
||||
{
|
||||
long i, d = leng / 3 + 1;
|
||||
long h = leng + 3, w = leng + d * 3 / 2 + 2;
|
||||
|
||||
/* allocate pixel buffer */
|
||||
rgb *buf = malloc(sizeof(rgb) * w * h);
|
||||
pix = malloc(sizeof(rgb *) * h);
|
||||
for (i = 0; i < h; i++)
|
||||
pix[i] = buf + w * i;
|
||||
memset(buf, 0, sizeof(rgb) * w * h);
|
||||
|
||||
/* init coords; scale up to desired; exec string */
|
||||
x = y = d; dx = leng; dy = 0; scale = 1; clen = 0;
|
||||
for (i = 0; i < depth; i++) sc_up();
|
||||
iter_string("FX", depth);
|
||||
|
||||
/* write color PNM file */
|
||||
unsigned char *fpix = malloc(w * h * 3);
|
||||
double maxv = 0, *dbuf = (double*)buf;
|
||||
|
||||
/* find highest value among pixels; normalize image according
|
||||
* to it. Highest value would be at points most travelled, so
|
||||
* this ends up giving curve edge a nice fade -- it's more apparaent
|
||||
* if we increase iteration depth by one or two.
|
||||
*/
|
||||
for (i = 3 * w * h - 1; i >= 0; i--)
|
||||
if (dbuf[i] > maxv) maxv = dbuf[i];
|
||||
for (i = 3 * h * w - 1; i >= 0; i--)
|
||||
fpix[i] = 255 * dbuf[i] / maxv;
|
||||
|
||||
printf("P6\n%ld %ld\n255\n", w, h);
|
||||
fflush(stdout); /* printf and fwrite may treat buffer differently */
|
||||
fwrite(fpix, h * w * 3, 1, stdout);
|
||||
}
|
||||
|
||||
int main(int c, char ** v)
|
||||
{
|
||||
int size, depth;
|
||||
|
||||
depth = (c > 1) ? atoi(v[1]) : 10;
|
||||
size = 1 << depth;
|
||||
|
||||
fprintf(stderr, "size: %d depth: %d\n", size, depth);
|
||||
dragon(size, depth * 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue