ref: 8af0c29615fdfe30035f2d4c3a7d2ccf06d6efa9
parent: 69773d855b517ea356c3c02add97893201de2066
author: Simon Tatham <anakin@pobox.com>
date: Sat Nov 18 10:16:40 EST 2017
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.
--- a/LICENCE
+++ b/LICENCE
@@ -2,7 +2,8 @@
Portions copyright Richard Boulton, James Harvey, Mike Pinna, Jonas
K�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
--- a/grid.c
+++ b/grid.c
@@ -2060,6 +2060,102 @@
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
--- a/grid.h
+++ b/grid.h
@@ -100,6 +100,7 @@
A(SNUBSQUARE,snubsquare) \
A(CAIRO,cairo) \
A(GREATHEXAGONAL,greathexagonal) \
+ A(KAGOME,kagome) \
A(OCTAGONAL,octagonal) \
A(KITE,kites) \
A(FLORET,floret) \
--- a/loopy.c
+++ b/loopy.c
@@ -278,6 +278,7 @@
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 @@
#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 @@
#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 },