diff options
Diffstat (limited to 'apps/plugins/puzzles/src/penrose.h')
-rw-r--r-- | apps/plugins/puzzles/src/penrose.h | 119 |
1 files changed, 73 insertions, 46 deletions
diff --git a/apps/plugins/puzzles/src/penrose.h b/apps/plugins/puzzles/src/penrose.h index ba5ae16f2c..e6e927d618 100644 --- a/apps/plugins/puzzles/src/penrose.h +++ b/apps/plugins/puzzles/src/penrose.h | |||
@@ -1,59 +1,86 @@ | |||
1 | /* penrose.h | 1 | #ifndef PUZZLES_PENROSE_H |
2 | * | 2 | #define PUZZLES_PENROSE_H |
3 | * Penrose tiling functions. | ||
4 | * | ||
5 | * Provides an interface with which to generate Penrose tilings | ||
6 | * by recursive subdivision of an initial tile of choice (one of the | ||
7 | * four sets of two pairs kite/dart, or thin/thick rhombus). | ||
8 | * | ||
9 | * You supply a callback function and a context pointer, which is | ||
10 | * called with each tile in turn: you choose how many times to recurse. | ||
11 | */ | ||
12 | 3 | ||
13 | #ifndef _PENROSE_H | 4 | struct PenrosePatchParams { |
14 | #define _PENROSE_H | 5 | /* |
6 | * A patch of Penrose tiling is identified by giving | ||
7 | * | ||
8 | * - the coordinates of the starting triangle, using a | ||
9 | * combinatorial coordinate system | ||
10 | * | ||
11 | * - which vertex of that triangle is at the centre point of the | ||
12 | * tiling | ||
13 | * | ||
14 | * - the orientation of the triangle's base edge, as a number | ||
15 | * from 0 to 9, measured in tenths of a turn | ||
16 | * | ||
17 | * Coordinates are a sequence of letters. For a P2 tiling all | ||
18 | * letters are from the set {A,B,U,V}; for P3, {C,D,X,Y}. | ||
19 | */ | ||
20 | unsigned start_vertex; | ||
21 | int orientation; | ||
22 | size_t ncoords; | ||
23 | char *coords; | ||
24 | }; | ||
15 | 25 | ||
16 | #ifndef PHI | 26 | #ifndef PENROSE_ENUM_DEFINED |
17 | #define PHI 1.6180339887 | 27 | #define PENROSE_ENUM_DEFINED |
28 | enum { PENROSE_P2, PENROSE_P3 }; | ||
18 | #endif | 29 | #endif |
19 | 30 | ||
20 | typedef struct vector vector; | 31 | bool penrose_valid_letter(char c, int which); |
21 | |||
22 | double v_x(vector *vs, int i); | ||
23 | double v_y(vector *vs, int i); | ||
24 | 32 | ||
25 | typedef struct penrose_state penrose_state; | 33 | /* |
26 | 34 | * Fill in PenrosePatchParams with a randomly selected set of | |
27 | /* Return non-zero to clip the tree here (i.e. not recurse | 35 | * coordinates, in enough detail to generate a patch of tiling filling |
28 | * below this tile). | 36 | * a w x h area. |
37 | * | ||
38 | * Units of measurement: the tiling will be oriented such that | ||
39 | * horizontal tile edges are possible (and therefore vertical ones are | ||
40 | * not). Therefore, all x-coordinates will be rational linear | ||
41 | * combinations of 1 and sqrt(5), and all y-coordinates will be | ||
42 | * sin(pi/5) times such a rational linear combination. By scaling up | ||
43 | * appropriately we can turn those rational combinations into | ||
44 | * _integer_ combinations, so we do. Therefore, w is measured in units | ||
45 | * of 1/4, and h is measured in units of sin(pi/5)/2, on a scale where | ||
46 | * a length of 1 corresponds to the legs of the acute isosceles | ||
47 | * triangles in the tiling (hence, the long edges of P2 kites and | ||
48 | * darts, or all edges of P3 rhombs). | ||
29 | * | 49 | * |
30 | * Parameters are state, vector array, npoints, depth. | 50 | * (In case it's useful, the y scale factor sin(pi/5)/2 is an |
31 | * ctx is inside state. | 51 | * algebraic number. Its minimal polynomial is 256x^4 - 80x^2 + 5.) |
52 | * | ||
53 | * The 'coords' field of the structure will be filled in with a new | ||
54 | * dynamically allocated array. Any previous pointer in that field | ||
55 | * will be overwritten. | ||
32 | */ | 56 | */ |
33 | typedef int (*tile_callback)(penrose_state *, vector *, int, int); | 57 | void penrose_tiling_randomise(struct PenrosePatchParams *params, int which, |
34 | 58 | int w, int h, random_state *rs); | |
35 | struct penrose_state { | ||
36 | int start_size; /* initial side length */ | ||
37 | int max_depth; /* Recursion depth */ | ||
38 | |||
39 | tile_callback new_tile; | ||
40 | void *ctx; /* for callback */ | ||
41 | }; | ||
42 | 59 | ||
43 | enum { PENROSE_P2, PENROSE_P3 }; | 60 | /* |
44 | 61 | * Validate a PenrosePatchParams to ensure it contains no illegal | |
45 | extern int penrose(penrose_state *state, int which, int angle); | 62 | * coordinates. Returns NULL if it's acceptable, or an error string if |
63 | * not. | ||
64 | */ | ||
65 | const char *penrose_tiling_params_invalid( | ||
66 | const struct PenrosePatchParams *params, int which); | ||
46 | 67 | ||
47 | /* Returns the side-length of a penrose tile at recursion level | 68 | /* |
48 | * gen, given a starting side length. */ | 69 | * Generate the actual set of Penrose tiles from a PenrosePatchParams, |
49 | extern double penrose_side_length(double start_size, int depth); | 70 | * passing each one to a callback. The callback receives the vertices |
71 | * of each point, in the form of an array of 4*4 integers. Each vertex | ||
72 | * is represented by four consecutive integers in this array, with the | ||
73 | * first two giving the x coordinate and the last two the y | ||
74 | * coordinate. Each pair of integers a,b represent a single coordinate | ||
75 | * whose value is a + b*sqrt(5). The units of measurement for x and y | ||
76 | * are as described above. | ||
77 | */ | ||
78 | typedef void (*penrose_tile_callback_fn)(void *ctx, const int *coords); | ||
50 | 79 | ||
51 | /* Returns the count of each type of tile at a given recursion depth. */ | 80 | #define PENROSE_NVERTICES 4 |
52 | extern void penrose_count_tiles(int gen, int *nlarge, int *nsmall); | ||
53 | 81 | ||
54 | /* Calculate start size and recursion depth required to produce a | 82 | void penrose_tiling_generate( |
55 | * width-by-height sized patch of penrose tiles with the given tilesize */ | 83 | const struct PenrosePatchParams *params, int w, int h, |
56 | extern void penrose_calculate_size(int which, int tilesize, int w, int h, | 84 | penrose_tile_callback_fn cb, void *cbctx); |
57 | double *required_radius, int *start_size, int *depth); | ||
58 | 85 | ||
59 | #endif | 86 | #endif |