#include #include #include #include "picture.h" #include "studio/geometry.h" #include "unreliableobjects.h" static inline double wobble(const double angle, const double width) { return angle + ((any(359) - 180.0) * 0.001 * (1.618 * width)); } static inline double length(const double angle) { return sine(angle / 2.0); } static struct object create(const size_t sides, const double linewidth) { assert(sides <= 360); const double angle = 360.0 / (double)sides; struct object object= { .vectors = (sides * magic) + 1, .transformation = translate( divide((vector){.x = -sine(angle / 2.0), .y = -cosine(angle / 2.0)}, scalar(2.0)), identity() ) }; assert(object.vectors <= count(object.vector)); polar turtle = {.distance = length(wobble(angle, linewidth))}; object.vector[0] = cartesian(turtle); for (size_t number = 1; number < object.vectors; ++number) { turtle = move(turtle, (polar){.distance = length(wobble(angle, linewidth)), .angle = wobble(angle, linewidth)}); object.vector[number] = add(cartesian(turtle), object.vector[number - 1]); } return object; } static struct picture draw(struct picture picture) { const size_t objects = count(picture.object); if (picture.sides) { const struct object object = create(picture.sides, picture.linewidth); for (size_t number = 0; number < objects; ++number) picture.object[number] = object; } else { if (picture.chaos) { size_t shuffled[count(picture.object)] = {1}; for (size_t number = 1; number < count(shuffled); ++number) { const size_t pick = any(number); shuffled[number] = shuffled[pick]; shuffled[pick] = number + 1; } for (size_t number = 0; number < objects; ++number) picture.object[number] = create(shuffled[number], picture.linewidth); } else { for (size_t number = 0; number < objects; ++number) picture.object[number] = create(number + 1, picture.linewidth); } } return picture; } static struct picture compose(struct picture picture) { const size_t objects = count(picture.object); const size_t columns = floor(objects / floor(sqrt(objects))); const double proportion = 9.0 / 11.0; const double center = (columns / (columns + 1.0)) + ((picture.linewidth / 200.0) * proportion); const matrix grid = scale( scalar((proportion / columns) * (1.0 - ((1.0 - proportion) / columns))), translate((vector){.x = 1.0 - center, .y = center}, identity()) ); for (size_t number = 0; number < objects; ++number) { const matrix transformation = rotate(any(359), scale(scalar(proportion), translate( (vector){.x = number % columns, .y = -(double)(number / columns)}, grid ))); picture.object[number].transformation = ( picture.chaos ? transformation : concatenate(picture.object[number].transformation, transformation) ); } return picture; } struct picture picture(const struct picture picture) { return compose(draw(picture)); } struct picture erase(struct picture picture) { const size_t objects = count(picture.object); for (size_t number = 0; number < objects; ++number) picture.object[number] = (struct object){0}; return picture; }