New grid type: the trihexagonal tiling, or 'kagome lattice'.

Regular hexagons and equilateral triangles in strict alternation, with
two of each interleaved around each vertex.
https://en.wikipedia.org/wiki/Trihexagonal_tiling

Thanks to Michael Quevillon for the patch.
This commit is contained in:
Simon Tatham
2017-11-18 15:16:40 +00:00
parent 69773d855b
commit 8af0c29615
4 changed files with 102 additions and 1 deletions

View File

@ -2,7 +2,8 @@ This software is copyright (c) 2004-2014 Simon Tatham.
Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
K<EFBFBD>lker, Dariusz Olszewski, Michael Schierl, Lambros Lambrou, Bernd
Schmidt, Steffen Bauer, Lennard Sprong and Rogier Goossens.
Schmidt, Steffen Bauer, Lennard Sprong, Rogier Goossens and Michael
Quevillon.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files

96
grid.c
View File

@ -2060,6 +2060,102 @@ static grid *grid_new_greathexagonal(int width, int height, const char *desc)
return g;
}
#define KAGOME_TILESIZE 18
/* Vector for side of triangle - ratio is close to sqrt(3) */
#define KAGOME_A 15
#define KAGOME_B 26
static void grid_size_kagome(int width, int height,
int *tilesize, int *xextent, int *yextent)
{
int a = KAGOME_A;
int b = KAGOME_B;
*tilesize = KAGOME_TILESIZE;
*xextent = (4*a) * (width-1) + 6*a;
*yextent = (2*b) * (height-1) + 2*b;
}
static grid *grid_new_kagome(int width, int height, const char *desc)
{
int x, y;
int a = KAGOME_A;
int b = KAGOME_B;
/* Upper bounds - don't have to be exact */
int max_faces = 6 * (width + 1) * (height + 1);
int max_dots = 6 * width * height;
tree234 *points;
grid *g = grid_empty();
g->tilesize = KAGOME_TILESIZE;
g->faces = snewn(max_faces, grid_face);
g->dots = snewn(max_dots, grid_dot);
points = newtree234(grid_point_cmp_fn);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
grid_dot *d;
/* centre of hexagon */
int px = (4*a) * x;
int py = (2*b) * y;
if (y % 2)
px += 2*a;
/* hexagon */
grid_face_add_new(g, 6);
d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 0);
d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1);
d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 2);
d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 3);
d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 4);
d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 5);
/* Triangle above right */
if ((x < width - 1) || (!(y % 2) && y)) {
grid_face_add_new(g, 3);
d = grid_get_dot(g, points, px + 3*a, py - b); grid_face_set_dot(g, d, 0);
d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 1);
d = grid_get_dot(g, points, px + a, py - b); grid_face_set_dot(g, d, 2);
}
/* Triangle below right */
if ((x < width - 1) || (!(y % 2) && (y < height - 1))) {
grid_face_add_new(g, 3);
d = grid_get_dot(g, points, px + 3*a, py + b); grid_face_set_dot(g, d, 0);
d = grid_get_dot(g, points, px + a, py + b); grid_face_set_dot(g, d, 1);
d = grid_get_dot(g, points, px + 2*a, py ); grid_face_set_dot(g, d, 2);
}
/* Left triangles */
if (!x && (y % 2)) {
/* Triangle above left */
grid_face_add_new(g, 3);
d = grid_get_dot(g, points, px - a, py - b); grid_face_set_dot(g, d, 0);
d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 1);
d = grid_get_dot(g, points, px - 3*a, py - b); grid_face_set_dot(g, d, 2);
/* Triangle below left */
if (y < height - 1) {
grid_face_add_new(g, 3);
d = grid_get_dot(g, points, px - a, py + b); grid_face_set_dot(g, d, 0);
d = grid_get_dot(g, points, px - 3*a, py + b); grid_face_set_dot(g, d, 1);
d = grid_get_dot(g, points, px - 2*a, py ); grid_face_set_dot(g, d, 2);
}
}
}
}
freetree234(points);
assert(g->num_faces <= max_faces);
assert(g->num_dots <= max_dots);
grid_make_consistent(g);
return g;
}
#define OCTAGONAL_TILESIZE 40
/* b/a approx sqrt(2) */
#define OCTAGONAL_A 29

1
grid.h
View File

@ -100,6 +100,7 @@ typedef struct grid {
A(SNUBSQUARE,snubsquare) \
A(CAIRO,cairo) \
A(GREATHEXAGONAL,greathexagonal) \
A(KAGOME,kagome) \
A(OCTAGONAL,octagonal) \
A(KITE,kites) \
A(FLORET,floret) \

View File

@ -278,6 +278,7 @@ static void check_caches(const solver_state* sstate);
A("Penrose (kite/dart)",PENROSE_P2,3,3) \
A("Penrose (rhombs)",PENROSE_P3,3,3) \
A("Great-Great-Dodecagonal",GREATGREATDODECAGONAL,2,2) \
A("Kagome",KAGOME,3,3) \
/* end of list */
#define GRID_NAME(title,type,amin,omin) title,
@ -544,6 +545,7 @@ static const game_params loopy_presets_more[] = {
#ifdef SMALL_SCREEN
{ 7, 7, DIFF_HARD, LOOPY_GRID_HONEYCOMB },
{ 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL },
{ 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME },
{ 5, 5, DIFF_HARD, LOOPY_GRID_OCTAGONAL },
{ 3, 3, DIFF_HARD, LOOPY_GRID_FLORET },
{ 3, 3, DIFF_HARD, LOOPY_GRID_DODECAGONAL },
@ -552,6 +554,7 @@ static const game_params loopy_presets_more[] = {
#else
{ 10, 10, DIFF_HARD, LOOPY_GRID_HONEYCOMB },
{ 5, 4, DIFF_HARD, LOOPY_GRID_GREATHEXAGONAL },
{ 5, 4, DIFF_HARD, LOOPY_GRID_KAGOME },
{ 7, 7, DIFF_HARD, LOOPY_GRID_OCTAGONAL },
{ 5, 5, DIFF_HARD, LOOPY_GRID_FLORET },
{ 5, 4, DIFF_HARD, LOOPY_GRID_DODECAGONAL },