grid.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * (c) Lambros Lambrou 2008
  3. *
  4. * Code for working with general grids, which can be any planar graph
  5. * with faces, edges and vertices (dots). Includes generators for a few
  6. * types of grid, including square, hexagonal, triangular and others.
  7. */
  8. #ifndef PUZZLES_GRID_H
  9. #define PUZZLES_GRID_H
  10. #include "puzzles.h" /* for random_state */
  11. /* Useful macros */
  12. #define SQ(x) ( (x) * (x) )
  13. /* ----------------------------------------------------------------------
  14. * Grid structures:
  15. * A grid is made up of faces, edges and dots. These structures hold
  16. * the incidence relationships between these types. For example, an
  17. * edge always joins two dots, and is adjacent to two faces.
  18. * The "grid_xxx **" members are lists of pointers which are dynamically
  19. * allocated during grid generation.
  20. * A pointer to a face/edge/dot will always point somewhere inside one of the
  21. * three lists of the main "grid" structure: faces, edges, dots.
  22. * Could have used integer offsets into these lists, but using actual
  23. * pointers instead gives us type-safety.
  24. */
  25. /* Need forward declarations */
  26. typedef struct grid_face grid_face;
  27. typedef struct grid_edge grid_edge;
  28. typedef struct grid_dot grid_dot;
  29. struct grid_face {
  30. int index; /* index in grid->faces[] where this face appears */
  31. int order; /* Number of edges, also the number of dots */
  32. grid_edge **edges; /* edges around this face */
  33. grid_dot **dots; /* corners of this face */
  34. /*
  35. * For each face, we optionally compute and store its 'incentre'.
  36. * The incentre of a triangle is the centre of a circle tangent to
  37. * all three edges; I generalise the concept to arbitrary polygons
  38. * by defining it to be the centre of the largest circle you can fit
  39. * anywhere in the polygon. It's a useful thing to know because if
  40. * you want to draw any symbol or text in the face (e.g. clue
  41. * numbers in Loopy), that's the place it will most easily fit.
  42. *
  43. * When a grid is first generated, no face has this information
  44. * computed, because it's fiddly to do. You can call
  45. * grid_find_incentre() on a face, and it will fill in ix,iy below
  46. * and set has_incentre to indicate that it's done so.
  47. */
  48. bool has_incentre;
  49. int ix, iy; /* incentre (centre of largest inscribed circle) */
  50. };
  51. struct grid_edge {
  52. grid_dot *dot1, *dot2;
  53. grid_face *face1, *face2; /* Use NULL for the infinite outside face */
  54. int index; /* index in grid->edges[] where this edge appears */
  55. };
  56. struct grid_dot {
  57. int index; /* index in grid->dots[] where this dot appears */
  58. int order;
  59. grid_edge **edges;
  60. grid_face **faces; /* A NULL grid_face* means infinite outside face */
  61. /* Position in some fairly arbitrary (Cartesian) coordinate system.
  62. * Use large enough values such that we can get away with
  63. * integer arithmetic, but small enough such that arithmetic
  64. * won't overflow. */
  65. int x, y;
  66. };
  67. typedef struct grid {
  68. /* Arrays of all the faces, edges, dots that are in the grid.
  69. * The arrays themselves are dynamically allocated, and so is each object
  70. * inside them. num_foo indicates the number of things actually stored,
  71. * and size_foo indicates the allocated size of the array. */
  72. int num_faces, size_faces; grid_face **faces;
  73. int num_edges, size_edges; grid_edge **edges;
  74. int num_dots, size_dots; grid_dot **dots;
  75. /* Cache the bounding-box of the grid, so the drawing-code can quickly
  76. * figure out the proper scaling to draw onto a given area. */
  77. int lowest_x, lowest_y, highest_x, highest_y;
  78. /* A measure of tile size for this grid (in grid coordinates), to help
  79. * the renderer decide how large to draw the grid.
  80. * Roughly the size of a single tile - for example the side-length
  81. * of a square cell. */
  82. int tilesize;
  83. /* We really don't want to copy this monstrosity!
  84. * A grid is immutable once generated.
  85. */
  86. int refcount;
  87. } grid;
  88. /* Grids are specified by type: GRID_SQUARE, GRID_KITE, etc. */
  89. #define GRIDGEN_LIST(A) \
  90. A(SQUARE,square) \
  91. A(HONEYCOMB,honeycomb) \
  92. A(TRIANGULAR,triangular) \
  93. A(SNUBSQUARE,snubsquare) \
  94. A(CAIRO,cairo) \
  95. A(GREATHEXAGONAL,greathexagonal) \
  96. A(KAGOME,kagome) \
  97. A(OCTAGONAL,octagonal) \
  98. A(KITE,kites) \
  99. A(FLORET,floret) \
  100. A(DODECAGONAL,dodecagonal) \
  101. A(GREATDODECAGONAL,greatdodecagonal) \
  102. A(GREATGREATDODECAGONAL,greatgreatdodecagonal) \
  103. A(COMPASSDODECAGONAL,compassdodecagonal) \
  104. A(PENROSE_P2,penrose_p2_kite) \
  105. A(PENROSE_P3,penrose_p3_thick) \
  106. A(HATS,hats) \
  107. A(SPECTRES,spectres) \
  108. /* end of list */
  109. #define ENUM(upper,lower) GRID_ ## upper,
  110. typedef enum grid_type { GRIDGEN_LIST(ENUM) GRID_TYPE_MAX } grid_type;
  111. #undef ENUM
  112. const char *grid_validate_params(grid_type type, int width, int height);
  113. /* Free directly after use if non-NULL. Will never contain an underscore
  114. * (so clients can safely use that as a separator). */
  115. char *grid_new_desc(grid_type type, int width, int height, random_state *rs);
  116. const char *grid_validate_desc(grid_type type, int width, int height,
  117. const char *desc);
  118. grid *grid_new(grid_type type, int width, int height, const char *desc);
  119. void grid_free(grid *g);
  120. grid_edge *grid_nearest_edge(grid *g, int x, int y);
  121. void grid_compute_size(grid_type type, int width, int height,
  122. int *tilesize, int *xextent, int *yextent);
  123. void grid_find_incentre(grid_face *f);
  124. #endif /* PUZZLES_GRID_H */