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

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