penrose.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #ifndef PUZZLES_PENROSE_H
  2. #define PUZZLES_PENROSE_H
  3. struct PenrosePatchParams {
  4. /*
  5. * A patch of Penrose tiling is identified by giving
  6. *
  7. * - the coordinates of the starting triangle, using a
  8. * combinatorial coordinate system
  9. *
  10. * - which vertex of that triangle is at the centre point of the
  11. * tiling
  12. *
  13. * - the orientation of the triangle's base edge, as a number
  14. * from 0 to 9, measured in tenths of a turn
  15. *
  16. * Coordinates are a sequence of letters. For a P2 tiling all
  17. * letters are from the set {A,B,U,V}; for P3, {C,D,X,Y}.
  18. */
  19. unsigned start_vertex;
  20. int orientation;
  21. size_t ncoords;
  22. char *coords;
  23. };
  24. #ifndef PENROSE_ENUM_DEFINED
  25. #define PENROSE_ENUM_DEFINED
  26. enum { PENROSE_P2, PENROSE_P3 };
  27. #endif
  28. bool penrose_valid_letter(char c, int which);
  29. /*
  30. * Fill in PenrosePatchParams with a randomly selected set of
  31. * coordinates, in enough detail to generate a patch of tiling filling
  32. * a w x h area.
  33. *
  34. * Units of measurement: the tiling will be oriented such that
  35. * horizontal tile edges are possible (and therefore vertical ones are
  36. * not). Therefore, all x-coordinates will be rational linear
  37. * combinations of 1 and sqrt(5), and all y-coordinates will be
  38. * sin(pi/5) times such a rational linear combination. By scaling up
  39. * appropriately we can turn those rational combinations into
  40. * _integer_ combinations, so we do. Therefore, w is measured in units
  41. * of 1/4, and h is measured in units of sin(pi/5)/2, on a scale where
  42. * a length of 1 corresponds to the legs of the acute isosceles
  43. * triangles in the tiling (hence, the long edges of P2 kites and
  44. * darts, or all edges of P3 rhombs).
  45. *
  46. * (In case it's useful, the y scale factor sin(pi/5)/2 is an
  47. * algebraic number. Its minimal polynomial is 256x^4 - 80x^2 + 5.)
  48. *
  49. * The 'coords' field of the structure will be filled in with a new
  50. * dynamically allocated array. Any previous pointer in that field
  51. * will be overwritten.
  52. */
  53. void penrose_tiling_randomise(struct PenrosePatchParams *params, int which,
  54. int w, int h, random_state *rs);
  55. /*
  56. * Validate a PenrosePatchParams to ensure it contains no illegal
  57. * coordinates. Returns NULL if it's acceptable, or an error string if
  58. * not.
  59. */
  60. const char *penrose_tiling_params_invalid(
  61. const struct PenrosePatchParams *params, int which);
  62. /*
  63. * Generate the actual set of Penrose tiles from a PenrosePatchParams,
  64. * passing each one to a callback. The callback receives the vertices
  65. * of each point, in the form of an array of 4*4 integers. Each vertex
  66. * is represented by four consecutive integers in this array, with the
  67. * first two giving the x coordinate and the last two the y
  68. * coordinate. Each pair of integers a,b represent a single coordinate
  69. * whose value is a + b*sqrt(5). The units of measurement for x and y
  70. * are as described above.
  71. */
  72. typedef void (*penrose_tile_callback_fn)(void *ctx, const int *coords);
  73. #define PENROSE_NVERTICES 4
  74. void penrose_tiling_generate(
  75. const struct PenrosePatchParams *params, int w, int h,
  76. penrose_tile_callback_fn cb, void *cbctx);
  77. #endif