chiark / gitweb /
Patch from James H to make new-Loopy port more easily.
[sgt-puzzles.git] / grid.c
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
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13 #include <ctype.h>
14 #include <math.h>
15
16 #include "puzzles.h"
17 #include "tree234.h"
18 #include "grid.h"
19
20 /* Debugging options */
21
22 /*
23 #define DEBUG_GRID
24 */
25
26 /* ----------------------------------------------------------------------
27  * Deallocate or dereference a grid
28  */
29 void grid_free(grid *g)
30 {
31     assert(g->refcount);
32
33     g->refcount--;
34     if (g->refcount == 0) {
35         int i;
36         for (i = 0; i < g->num_faces; i++) {
37             sfree(g->faces[i].dots);
38             sfree(g->faces[i].edges);
39         }
40         for (i = 0; i < g->num_dots; i++) {
41             sfree(g->dots[i].faces);
42             sfree(g->dots[i].edges);
43         }
44         sfree(g->faces);
45         sfree(g->edges);
46         sfree(g->dots);
47         sfree(g);
48     }
49 }
50
51 /* Used by the other grid generators.  Create a brand new grid with nothing
52  * initialised (all lists are NULL) */
53 static grid *grid_new(void)
54 {
55     grid *g = snew(grid);
56     g->faces = NULL;
57     g->edges = NULL;
58     g->dots = NULL;
59     g->num_faces = g->num_edges = g->num_dots = 0;
60     g->middle_face = NULL;
61     g->refcount = 1;
62     g->lowest_x = g->lowest_y = g->highest_x = g->highest_y = 0;
63     return g;
64 }
65
66 /* Helper function to calculate perpendicular distance from
67  * a point P to a line AB.  A and B mustn't be equal here.
68  *
69  * Well-known formula for area A of a triangle:
70  *                             /  1   1   1 \
71  * 2A = determinant of matrix  | px  ax  bx |
72  *                             \ py  ay  by /
73  *
74  * Also well-known: 2A = base * height
75  *                     = perpendicular distance * line-length.
76  *
77  * Combining gives: distance = determinant / line-length(a,b)
78  */
79 static double point_line_distance(long px, long py,
80                                   long ax, long ay,
81                                   long bx, long by)
82 {
83     long det = ax*by - bx*ay + bx*py - px*by + px*ay - ax*py;
84     double len;
85     det = max(det, -det);
86     len = sqrt(SQ(ax - bx) + SQ(ay - by));
87     return det / len;
88 }
89
90 /* Determine nearest edge to where the user clicked.
91  * (x, y) is the clicked location, converted to grid coordinates.
92  * Returns the nearest edge, or NULL if no edge is reasonably
93  * near the position.
94  *
95  * This algorithm is nice and generic, and doesn't depend on any particular
96  * geometric layout of the grid:
97  *   Start at any dot (pick one next to middle_face).
98  *   Walk along a path by choosing, from all nearby dots, the one that is
99  *   nearest the target (x,y).  Hopefully end up at the dot which is closest
100  *   to (x,y).  Should work, as long as faces aren't too badly shaped.
101  *   Then examine each edge around this dot, and pick whichever one is
102  *   closest (perpendicular distance) to (x,y).
103  *   Using perpendicular distance is not quite right - the edge might be
104  *   "off to one side".  So we insist that the triangle with (x,y) has
105  *   acute angles at the edge's dots.
106  *
107  *     edge1
108  *  *---------*------
109  *            |
110  *            |      *(x,y)
111  *      edge2 |
112  *            |   edge2 is OK, but edge1 is not, even though
113  *            |   edge1 is perpendicularly closer to (x,y)
114  *            *
115  *
116  */
117 grid_edge *grid_nearest_edge(grid *g, int x, int y)
118 {
119     grid_dot *cur;
120     grid_edge *best_edge;
121     double best_distance = 0;
122     int i;
123
124     cur = g->middle_face->dots[0];
125
126     for (;;) {
127         /* Target to beat */
128         long dist = SQ((long)cur->x - (long)x) + SQ((long)cur->y - (long)y);
129         /* Look for nearer dot - if found, store in 'new'. */
130         grid_dot *new = cur;
131         int i;
132         /* Search all dots in all faces touching this dot.  Some shapes
133          * (such as in Cairo) don't quite work properly if we only search
134          * the dot's immediate neighbours. */
135         for (i = 0; i < cur->order; i++) {
136             grid_face *f = cur->faces[i];
137             int j;
138             if (!f) continue;
139             for (j = 0; j < f->order; j++) {
140                 long new_dist;
141                 grid_dot *d = f->dots[j];
142                 if (d == cur) continue;
143                 new_dist = SQ((long)d->x - (long)x) + SQ((long)d->y - (long)y);
144                 if (new_dist < dist) {
145                     new = d;
146                     break; /* found closer dot */
147                 }
148             }
149             if (new != cur)
150                 break; /* found closer dot */
151         }
152
153         if (new == cur) {
154             /* Didn't find a closer dot among the neighbours of 'cur' */
155             break;
156         } else {
157             cur = new;
158         }
159     }
160     /* 'cur' is nearest dot, so find which of the dot's edges is closest. */
161     best_edge = NULL;
162
163     for (i = 0; i < cur->order; i++) {
164         grid_edge *e = cur->edges[i];
165         long e2; /* squared length of edge */
166         long a2, b2; /* squared lengths of other sides */
167         double dist;
168
169         /* See if edge e is eligible - the triangle must have acute angles
170          * at the edge's dots.
171          * Pythagoras formula h^2 = a^2 + b^2 detects right-angles,
172          * so detect acute angles by testing for h^2 < a^2 + b^2 */
173         e2 = SQ((long)e->dot1->x - (long)e->dot2->x) + SQ((long)e->dot1->y - (long)e->dot2->y);
174         a2 = SQ((long)e->dot1->x - (long)x) + SQ((long)e->dot1->y - (long)y);
175         b2 = SQ((long)e->dot2->x - (long)x) + SQ((long)e->dot2->y - (long)y);
176         if (a2 >= e2 + b2) continue;
177         if (b2 >= e2 + a2) continue;
178          
179         /* e is eligible so far.  Now check the edge is reasonably close
180          * to where the user clicked.  Don't want to toggle an edge if the
181          * click was way off the grid.
182          * There is room for experimentation here.  We could check the
183          * perpendicular distance is within a certain fraction of the length
184          * of the edge.  That amounts to testing a rectangular region around
185          * the edge.
186          * Alternatively, we could check that the angle at the point is obtuse.
187          * That would amount to testing a circular region with the edge as
188          * diameter. */
189         dist = point_line_distance((long)x, (long)y,
190                                    (long)e->dot1->x, (long)e->dot1->y,
191                                    (long)e->dot2->x, (long)e->dot2->y);
192         /* Is dist more than half edge length ? */
193         if (4 * SQ(dist) > e2)
194             continue;
195
196         if (best_edge == NULL || dist < best_distance) {
197             best_edge = e;
198             best_distance = dist;
199         }
200     }
201     return best_edge;
202 }
203
204 /* ----------------------------------------------------------------------
205  * Grid generation
206  */
207
208 #ifdef DEBUG_GRID
209 /* Show the basic grid information, before doing grid_make_consistent */
210 static void grid_print_basic(grid *g)
211 {
212     /* TODO: Maybe we should generate an SVG image of the dots and lines
213      * of the grid here, before grid_make_consistent.
214      * Would help with debugging grid generation. */
215     int i;
216     printf("--- Basic Grid Data ---\n");
217     for (i = 0; i < g->num_faces; i++) {
218         grid_face *f = g->faces + i;
219         printf("Face %d: dots[", i);
220         int j;
221         for (j = 0; j < f->order; j++) {
222             grid_dot *d = f->dots[j];
223             printf("%s%d", j ? "," : "", (int)(d - g->dots)); 
224         }
225         printf("]\n");
226     }
227     printf("Middle face: %d\n", (int)(g->middle_face - g->faces));
228 }
229 /* Show the derived grid information, computed by grid_make_consistent */
230 static void grid_print_derived(grid *g)
231 {
232     /* edges */
233     int i;
234     printf("--- Derived Grid Data ---\n");
235     for (i = 0; i < g->num_edges; i++) {
236         grid_edge *e = g->edges + i;
237         printf("Edge %d: dots[%d,%d] faces[%d,%d]\n",
238             i, (int)(e->dot1 - g->dots), (int)(e->dot2 - g->dots),
239             e->face1 ? (int)(e->face1 - g->faces) : -1,
240             e->face2 ? (int)(e->face2 - g->faces) : -1);
241     }
242     /* faces */
243     for (i = 0; i < g->num_faces; i++) {
244         grid_face *f = g->faces + i;
245         int j;
246         printf("Face %d: faces[", i);
247         for (j = 0; j < f->order; j++) {
248             grid_edge *e = f->edges[j];
249             grid_face *f2 = (e->face1 == f) ? e->face2 : e->face1;
250             printf("%s%d", j ? "," : "", f2 ? (int)(f2 - g->faces) : -1);
251         }
252         printf("]\n");
253     }
254     /* dots */
255     for (i = 0; i < g->num_dots; i++) {
256         grid_dot *d = g->dots + i;
257         int j;
258         printf("Dot %d: dots[", i);
259         for (j = 0; j < d->order; j++) {
260             grid_edge *e = d->edges[j];
261             grid_dot *d2 = (e->dot1 == d) ? e->dot2 : e->dot1;
262             printf("%s%d", j ? "," : "", (int)(d2 - g->dots));
263         }
264         printf("] faces[");
265         for (j = 0; j < d->order; j++) {
266             grid_face *f = d->faces[j];
267             printf("%s%d", j ? "," : "", f ? (int)(f - g->faces) : -1);
268         }
269         printf("]\n");
270     }
271 }
272 #endif /* DEBUG_GRID */
273
274 /* Helper function for building incomplete-edges list in
275  * grid_make_consistent() */
276 static int grid_edge_bydots_cmpfn(void *v1, void *v2)
277 {
278     grid_edge *a = v1;
279     grid_edge *b = v2;
280     grid_dot *da, *db;
281
282     /* Pointer subtraction is valid here, because all dots point into the
283      * same dot-list (g->dots).
284      * Edges are not "normalised" - the 2 dots could be stored in any order,
285      * so we need to take this into account when comparing edges. */
286
287     /* Compare first dots */
288     da = (a->dot1 < a->dot2) ? a->dot1 : a->dot2;
289     db = (b->dot1 < b->dot2) ? b->dot1 : b->dot2;
290     if (da != db)
291         return db - da;
292     /* Compare last dots */
293     da = (a->dot1 < a->dot2) ? a->dot2 : a->dot1;
294     db = (b->dot1 < b->dot2) ? b->dot2 : b->dot1;
295     if (da != db)
296         return db - da;
297
298     return 0;
299 }
300
301 /* Input: grid has its dots and faces initialised:
302  * - dots have (optionally) x and y coordinates, but no edges or faces
303  * (pointers are NULL).
304  * - edges not initialised at all
305  * - faces initialised and know which dots they have (but no edges yet).  The
306  * dots around each face are assumed to be clockwise.
307  *
308  * Output: grid is complete and valid with all relationships defined.
309  */
310 static void grid_make_consistent(grid *g)
311 {
312     int i;
313     tree234 *incomplete_edges;
314     grid_edge *next_new_edge; /* Where new edge will go into g->edges */
315
316 #ifdef DEBUG_GRID
317     grid_print_basic(g);
318 #endif
319
320     /* ====== Stage 1 ======
321      * Generate edges
322      */
323
324     /* We know how many dots and faces there are, so we can find the exact
325      * number of edges from Euler's polyhedral formula: F + V = E + 2 .
326      * We use "-1", not "-2" here, because Euler's formula includes the
327      * infinite face, which we don't count. */
328     g->num_edges = g->num_faces + g->num_dots - 1;
329     g->edges = snewn(g->num_edges, grid_edge);
330     next_new_edge = g->edges;
331
332     /* Iterate over faces, and over each face's dots, generating edges as we
333      * go.  As we find each new edge, we can immediately fill in the edge's
334      * dots, but only one of the edge's faces.  Later on in the iteration, we
335      * will find the same edge again (unless it's on the border), but we will
336      * know the other face.
337      * For efficiency, maintain a list of the incomplete edges, sorted by
338      * their dots. */
339     incomplete_edges = newtree234(grid_edge_bydots_cmpfn);
340     for (i = 0; i < g->num_faces; i++) {
341         grid_face *f = g->faces + i;
342         int j;
343         for (j = 0; j < f->order; j++) {
344             grid_edge e; /* fake edge for searching */
345             grid_edge *edge_found;
346             int j2 = j + 1;
347             if (j2 == f->order)
348                 j2 = 0;
349             e.dot1 = f->dots[j];
350             e.dot2 = f->dots[j2];
351             /* Use del234 instead of find234, because we always want to
352              * remove the edge if found */
353             edge_found = del234(incomplete_edges, &e);
354             if (edge_found) {
355                 /* This edge already added, so fill out missing face.
356                  * Edge is already removed from incomplete_edges. */
357                 edge_found->face2 = f;
358             } else {
359                 assert(next_new_edge - g->edges < g->num_edges);
360                 next_new_edge->dot1 = e.dot1;
361                 next_new_edge->dot2 = e.dot2;
362                 next_new_edge->face1 = f;
363                 next_new_edge->face2 = NULL; /* potentially infinite face */
364                 add234(incomplete_edges, next_new_edge);
365                 ++next_new_edge;
366             }
367         }
368     }
369     freetree234(incomplete_edges);
370     
371     /* ====== Stage 2 ======
372      * For each face, build its edge list.
373      */
374
375     /* Allocate space for each edge list.  Can do this, because each face's
376      * edge-list is the same size as its dot-list. */
377     for (i = 0; i < g->num_faces; i++) {
378         grid_face *f = g->faces + i;
379         int j;
380         f->edges = snewn(f->order, grid_edge*);
381         /* Preload with NULLs, to help detect potential bugs. */
382         for (j = 0; j < f->order; j++)
383             f->edges[j] = NULL;
384     }
385     
386     /* Iterate over each edge, and over both its faces.  Add this edge to
387      * the face's edge-list, after finding where it should go in the
388      * sequence. */
389     for (i = 0; i < g->num_edges; i++) {
390         grid_edge *e = g->edges + i;
391         int j;
392         for (j = 0; j < 2; j++) {
393             grid_face *f = j ? e->face2 : e->face1;
394             int k, k2;
395             if (f == NULL) continue;
396             /* Find one of the dots around the face */
397             for (k = 0; k < f->order; k++) {
398                 if (f->dots[k] == e->dot1)
399                     break; /* found dot1 */
400             }
401             assert(k != f->order); /* Must find the dot around this face */
402
403             /* Labelling scheme: as we walk clockwise around the face,
404              * starting at dot0 (f->dots[0]), we hit:
405              * (dot0), edge0, dot1, edge1, dot2,...
406              *
407              *     0
408              *  0-----1
409              *        |
410              *        |1
411              *        |
412              *  3-----2
413              *     2
414              *
415              * Therefore, edgeK joins dotK and dot{K+1}
416              */
417             
418             /* Around this face, either the next dot or the previous dot
419              * must be e->dot2.  Otherwise the edge is wrong. */
420             k2 = k + 1;
421             if (k2 == f->order)
422                 k2 = 0;
423             if (f->dots[k2] == e->dot2) {
424                 /* dot1(k) and dot2(k2) go clockwise around this face, so add
425                  * this edge at position k (see diagram). */
426                 assert(f->edges[k] == NULL);
427                 f->edges[k] = e;
428                 continue;
429             }
430             /* Try previous dot */
431             k2 = k - 1;
432             if (k2 == -1)
433                 k2 = f->order - 1;
434             if (f->dots[k2] == e->dot2) {
435                 /* dot1(k) and dot2(k2) go anticlockwise around this face. */
436                 assert(f->edges[k2] == NULL);
437                 f->edges[k2] = e;
438                 continue;
439             }
440             assert(!"Grid broken: bad edge-face relationship");
441         }
442     }
443
444     /* ====== Stage 3 ======
445      * For each dot, build its edge-list and face-list.
446      */
447
448     /* We don't know how many edges/faces go around each dot, so we can't
449      * allocate the right space for these lists.  Pre-compute the sizes by
450      * iterating over each edge and recording a tally against each dot. */
451     for (i = 0; i < g->num_dots; i++) {
452         g->dots[i].order = 0;
453     }
454     for (i = 0; i < g->num_edges; i++) {
455         grid_edge *e = g->edges + i;
456         ++(e->dot1->order);
457         ++(e->dot2->order);
458     }
459     /* Now we have the sizes, pre-allocate the edge and face lists. */
460     for (i = 0; i < g->num_dots; i++) {
461         grid_dot *d = g->dots + i;
462         int j;
463         assert(d->order >= 2); /* sanity check */
464         d->edges = snewn(d->order, grid_edge*);
465         d->faces = snewn(d->order, grid_face*);
466         for (j = 0; j < d->order; j++) {
467             d->edges[j] = NULL;
468             d->faces[j] = NULL;
469         }
470     }
471     /* For each dot, need to find a face that touches it, so we can seed
472      * the edge-face-edge-face process around each dot. */
473     for (i = 0; i < g->num_faces; i++) {
474         grid_face *f = g->faces + i;
475         int j;
476         for (j = 0; j < f->order; j++) {
477             grid_dot *d = f->dots[j];
478             d->faces[0] = f;
479         }
480     }
481     /* Each dot now has a face in its first slot.  Generate the remaining
482      * faces and edges around the dot, by searching both clockwise and
483      * anticlockwise from the first face.  Need to do both directions,
484      * because of the possibility of hitting the infinite face, which
485      * blocks progress.  But there's only one such face, so we will
486      * succeed in finding every edge and face this way. */
487     for (i = 0; i < g->num_dots; i++) {
488         grid_dot *d = g->dots + i;
489         int current_face1 = 0; /* ascends clockwise */
490         int current_face2 = 0; /* descends anticlockwise */
491         
492         /* Labelling scheme: as we walk clockwise around the dot, starting
493          * at face0 (d->faces[0]), we hit:
494          * (face0), edge0, face1, edge1, face2,...
495          *
496          *       0
497          *       |
498          *    0  |  1
499          *       |
500          *  -----d-----1
501          *       |
502          *       |  2
503          *       |
504          *       2
505          *
506          * So, for example, face1 should be joined to edge0 and edge1,
507          * and those edges should appear in an anticlockwise sense around
508          * that face (see diagram). */
509  
510         /* clockwise search */
511         while (TRUE) {
512             grid_face *f = d->faces[current_face1];
513             grid_edge *e;
514             int j;
515             assert(f != NULL);
516             /* find dot around this face */
517             for (j = 0; j < f->order; j++) {
518                 if (f->dots[j] == d)
519                     break;
520             }
521             assert(j != f->order); /* must find dot */
522             
523             /* Around f, required edge is anticlockwise from the dot.  See
524              * the other labelling scheme higher up, for why we subtract 1
525              * from j. */
526             j--;
527             if (j == -1)
528                 j = f->order - 1;
529             e = f->edges[j];
530             d->edges[current_face1] = e; /* set edge */
531             current_face1++;
532             if (current_face1 == d->order)
533                 break;
534             else {
535                 /* set face */
536                 d->faces[current_face1] =
537                     (e->face1 == f) ? e->face2 : e->face1;
538                 if (d->faces[current_face1] == NULL)
539                     break; /* cannot progress beyond infinite face */
540             }
541         }
542         /* If the clockwise search made it all the way round, don't need to
543          * bother with the anticlockwise search. */
544         if (current_face1 == d->order)
545             continue; /* this dot is complete, move on to next dot */
546         
547         /* anticlockwise search */
548         while (TRUE) {
549             grid_face *f = d->faces[current_face2];
550             grid_edge *e;
551             int j;
552             assert(f != NULL);
553             /* find dot around this face */
554             for (j = 0; j < f->order; j++) {
555                 if (f->dots[j] == d)
556                     break;
557             }
558             assert(j != f->order); /* must find dot */
559             
560             /* Around f, required edge is clockwise from the dot. */
561             e = f->edges[j];
562             
563             current_face2--;
564             if (current_face2 == -1)
565                 current_face2 = d->order - 1;
566             d->edges[current_face2] = e; /* set edge */
567
568             /* set face */
569             if (current_face2 == current_face1)
570                 break;
571             d->faces[current_face2] =
572                     (e->face1 == f) ? e->face2 : e->face1;
573             /* There's only 1 infinite face, so we must get all the way
574              * to current_face1 before we hit it. */
575             assert(d->faces[current_face2]);
576         }
577     }
578
579     /* ====== Stage 4 ======
580      * Compute other grid settings
581      */
582
583     /* Bounding rectangle */
584     for (i = 0; i < g->num_dots; i++) {
585         grid_dot *d = g->dots + i;
586         if (i == 0) {
587             g->lowest_x = g->highest_x = d->x;
588             g->lowest_y = g->highest_y = d->y;
589         } else {
590             g->lowest_x = min(g->lowest_x, d->x);
591             g->highest_x = max(g->highest_x, d->x);
592             g->lowest_y = min(g->lowest_y, d->y);
593             g->highest_y = max(g->highest_y, d->y);
594         }
595     }
596     
597 #ifdef DEBUG_GRID
598     grid_print_derived(g);
599 #endif
600 }
601
602 /* Helpers for making grid-generation easier.  These functions are only
603  * intended for use during grid generation. */
604
605 /* Comparison function for the (tree234) sorted dot list */
606 static int grid_point_cmp_fn(void *v1, void *v2)
607 {
608     grid_dot *p1 = v1;
609     grid_dot *p2 = v2;
610     if (p1->y != p2->y)
611         return p2->y - p1->y;
612     else
613         return p2->x - p1->x;
614 }
615 /* Add a new face to the grid, with its dot list allocated.
616  * Assumes there's enough space allocated for the new face in grid->faces */
617 static void grid_face_add_new(grid *g, int face_size)
618 {
619     int i;
620     grid_face *new_face = g->faces + g->num_faces;
621     new_face->order = face_size;
622     new_face->dots = snewn(face_size, grid_dot*);
623     for (i = 0; i < face_size; i++)
624         new_face->dots[i] = NULL;
625     new_face->edges = NULL;
626     g->num_faces++;
627 }
628 /* Assumes dot list has enough space */
629 static grid_dot *grid_dot_add_new(grid *g, int x, int y)
630 {
631     grid_dot *new_dot = g->dots + g->num_dots;
632     new_dot->order = 0;
633     new_dot->edges = NULL;
634     new_dot->faces = NULL;
635     new_dot->x = x;
636     new_dot->y = y;
637     g->num_dots++;
638     return new_dot;
639 }
640 /* Retrieve a dot with these (x,y) coordinates.  Either return an existing dot
641  * in the dot_list, or add a new dot to the grid (and the dot_list) and
642  * return that.
643  * Assumes g->dots has enough capacity allocated */
644 static grid_dot *grid_get_dot(grid *g, tree234 *dot_list, int x, int y)
645 {
646     grid_dot test = {0, NULL, NULL, x, y};
647     grid_dot *ret = find234(dot_list, &test, NULL);
648     if (ret)
649         return ret;
650
651     ret = grid_dot_add_new(g, x, y);
652     add234(dot_list, ret);
653     return ret;
654 }
655
656 /* Sets the last face of the grid to include this dot, at this position
657  * around the face. Assumes num_faces is at least 1 (a new face has
658  * previously been added, with the required number of dots allocated) */
659 static void grid_face_set_dot(grid *g, grid_dot *d, int position)
660 {
661     grid_face *last_face = g->faces + g->num_faces - 1;
662     last_face->dots[position] = d;
663 }
664
665 /* ------ Generate various types of grid ------ */
666
667 /* General method is to generate faces, by calculating their dot coordinates.
668  * As new faces are added, we keep track of all the dots so we can tell when
669  * a new face reuses an existing dot.  For example, two squares touching at an
670  * edge would generate six unique dots: four dots from the first face, then
671  * two additional dots for the second face, because we detect the other two
672  * dots have already been taken up.  This list is stored in a tree234
673  * called "points".  No extra memory-allocation needed here - we store the
674  * actual grid_dot* pointers, which all point into the g->dots list.
675  * For this reason, we have to calculate coordinates in such a way as to
676  * eliminate any rounding errors, so we can detect when a dot on one
677  * face precisely lands on a dot of a different face.  No floating-point
678  * arithmetic here!
679  */
680
681 grid *grid_new_square(int width, int height)
682 {
683     int x, y;
684     /* Side length */
685     int a = 20;
686
687     /* Upper bounds - don't have to be exact */
688     int max_faces = width * height;
689     int max_dots = (width + 1) * (height + 1);
690
691     tree234 *points;
692
693     grid *g = grid_new();
694     g->tilesize = a;
695     g->faces = snewn(max_faces, grid_face);
696     g->dots = snewn(max_dots, grid_dot);
697
698     points = newtree234(grid_point_cmp_fn);
699
700     /* generate square faces */
701     for (y = 0; y < height; y++) {
702         for (x = 0; x < width; x++) {
703             grid_dot *d;
704             /* face position */
705             int px = a * x;
706             int py = a * y;
707
708             grid_face_add_new(g, 4);
709             d = grid_get_dot(g, points, px, py);
710             grid_face_set_dot(g, d, 0);
711             d = grid_get_dot(g, points, px + a, py);
712             grid_face_set_dot(g, d, 1);
713             d = grid_get_dot(g, points, px + a, py + a);
714             grid_face_set_dot(g, d, 2);
715             d = grid_get_dot(g, points, px, py + a);
716             grid_face_set_dot(g, d, 3);
717         }
718     }
719
720     freetree234(points);
721     assert(g->num_faces <= max_faces);
722     assert(g->num_dots <= max_dots);
723     g->middle_face = g->faces + (height/2) * width + (width/2);
724
725     grid_make_consistent(g);
726     return g;
727 }
728
729 grid *grid_new_honeycomb(int width, int height)
730 {
731     int x, y;
732     /* Vector for side of hexagon - ratio is close to sqrt(3) */
733     int a = 15;
734     int b = 26;
735
736     /* Upper bounds - don't have to be exact */
737     int max_faces = width * height;
738     int max_dots = 2 * (width + 1) * (height + 1);
739     
740     tree234 *points;
741
742     grid *g = grid_new();
743     g->tilesize = 3 * a;
744     g->faces = snewn(max_faces, grid_face);
745     g->dots = snewn(max_dots, grid_dot);
746
747     points = newtree234(grid_point_cmp_fn);
748
749     /* generate hexagonal faces */
750     for (y = 0; y < height; y++) {
751         for (x = 0; x < width; x++) {
752             grid_dot *d;
753             /* face centre */
754             int cx = 3 * a * x;
755             int cy = 2 * b * y;
756             if (x % 2)
757                 cy += b;
758             grid_face_add_new(g, 6);
759
760             d = grid_get_dot(g, points, cx - a, cy - b);
761             grid_face_set_dot(g, d, 0);
762             d = grid_get_dot(g, points, cx + a, cy - b);
763             grid_face_set_dot(g, d, 1);
764             d = grid_get_dot(g, points, cx + 2*a, cy);
765             grid_face_set_dot(g, d, 2);
766             d = grid_get_dot(g, points, cx + a, cy + b);
767             grid_face_set_dot(g, d, 3);
768             d = grid_get_dot(g, points, cx - a, cy + b);
769             grid_face_set_dot(g, d, 4);
770             d = grid_get_dot(g, points, cx - 2*a, cy);
771             grid_face_set_dot(g, d, 5);
772         }
773     }
774
775     freetree234(points);
776     assert(g->num_faces <= max_faces);
777     assert(g->num_dots <= max_dots);
778     g->middle_face = g->faces + (height/2) * width + (width/2);
779
780     grid_make_consistent(g);
781     return g;
782 }
783
784 /* Doesn't use the previous method of generation, it pre-dates it!
785  * A triangular grid is just about simple enough to do by "brute force" */
786 grid *grid_new_triangular(int width, int height)
787 {
788     int x,y;
789     
790     /* Vector for side of triangle - ratio is close to sqrt(3) */
791     int vec_x = 15;
792     int vec_y = 26;
793     
794     int index;
795
796     /* convenient alias */
797     int w = width + 1;
798
799     grid *g = grid_new();
800     g->tilesize = 18; /* adjust to your taste */
801
802     g->num_faces = width * height * 2;
803     g->num_dots = (width + 1) * (height + 1);
804     g->faces = snewn(g->num_faces, grid_face);
805     g->dots = snewn(g->num_dots, grid_dot);
806
807     /* generate dots */
808     index = 0;
809     for (y = 0; y <= height; y++) {
810         for (x = 0; x <= width; x++) {
811             grid_dot *d = g->dots + index;
812             /* odd rows are offset to the right */
813             d->order = 0;
814             d->edges = NULL;
815             d->faces = NULL;
816             d->x = x * 2 * vec_x + ((y % 2) ? vec_x : 0);
817             d->y = y * vec_y;
818             index++;
819         }
820     }
821     
822     /* generate faces */
823     index = 0;
824     for (y = 0; y < height; y++) {
825         for (x = 0; x < width; x++) {
826             /* initialise two faces for this (x,y) */
827             grid_face *f1 = g->faces + index;
828             grid_face *f2 = f1 + 1;
829             f1->edges = NULL;
830             f1->order = 3;
831             f1->dots = snewn(f1->order, grid_dot*);
832             f2->edges = NULL;
833             f2->order = 3;
834             f2->dots = snewn(f2->order, grid_dot*);
835
836             /* face descriptions depend on whether the row-number is
837              * odd or even */
838             if (y % 2) {
839                 f1->dots[0] = g->dots + y       * w + x;
840                 f1->dots[1] = g->dots + (y + 1) * w + x + 1;
841                 f1->dots[2] = g->dots + (y + 1) * w + x;
842                 f2->dots[0] = g->dots + y       * w + x;
843                 f2->dots[1] = g->dots + y       * w + x + 1;
844                 f2->dots[2] = g->dots + (y + 1) * w + x + 1;
845             } else {
846                 f1->dots[0] = g->dots + y       * w + x;
847                 f1->dots[1] = g->dots + y       * w + x + 1;
848                 f1->dots[2] = g->dots + (y + 1) * w + x;
849                 f2->dots[0] = g->dots + y       * w + x + 1;
850                 f2->dots[1] = g->dots + (y + 1) * w + x + 1;
851                 f2->dots[2] = g->dots + (y + 1) * w + x;
852             }
853             index += 2;
854         }
855     }
856
857     /* "+ width" takes us to the middle of the row, because each row has
858      * (2*width) faces. */
859     g->middle_face = g->faces + (height / 2) * 2 * width + width;
860
861     grid_make_consistent(g);
862     return g;
863 }
864
865 grid *grid_new_snubsquare(int width, int height)
866 {
867     int x, y;
868     /* Vector for side of triangle - ratio is close to sqrt(3) */
869     int a = 15;
870     int b = 26;
871
872     /* Upper bounds - don't have to be exact */
873     int max_faces = 3 * width * height;
874     int max_dots = 2 * (width + 1) * (height + 1);
875     
876     tree234 *points;
877
878     grid *g = grid_new();
879     g->tilesize = 18;
880     g->faces = snewn(max_faces, grid_face);
881     g->dots = snewn(max_dots, grid_dot);
882
883     points = newtree234(grid_point_cmp_fn);
884
885     for (y = 0; y < height; y++) {
886         for (x = 0; x < width; x++) {
887             grid_dot *d;
888             /* face position */
889             int px = (a + b) * x;
890             int py = (a + b) * y;
891
892             /* generate square faces */
893             grid_face_add_new(g, 4);
894             if ((x + y) % 2) {
895                 d = grid_get_dot(g, points, px + a, py);
896                 grid_face_set_dot(g, d, 0);
897                 d = grid_get_dot(g, points, px + a + b, py + a);
898                 grid_face_set_dot(g, d, 1);
899                 d = grid_get_dot(g, points, px + b, py + a + b);
900                 grid_face_set_dot(g, d, 2);
901                 d = grid_get_dot(g, points, px, py + b);
902                 grid_face_set_dot(g, d, 3);
903             } else {
904                 d = grid_get_dot(g, points, px + b, py);
905                 grid_face_set_dot(g, d, 0);
906                 d = grid_get_dot(g, points, px + a + b, py + b);
907                 grid_face_set_dot(g, d, 1);
908                 d = grid_get_dot(g, points, px + a, py + a + b);
909                 grid_face_set_dot(g, d, 2);
910                 d = grid_get_dot(g, points, px, py + a);
911                 grid_face_set_dot(g, d, 3);
912             }
913
914             /* generate up/down triangles */
915             if (x > 0) {
916                 grid_face_add_new(g, 3);
917                 if ((x + y) % 2) {
918                     d = grid_get_dot(g, points, px + a, py);
919                     grid_face_set_dot(g, d, 0);
920                     d = grid_get_dot(g, points, px, py + b);
921                     grid_face_set_dot(g, d, 1);
922                     d = grid_get_dot(g, points, px - a, py);
923                     grid_face_set_dot(g, d, 2);
924                 } else {
925                     d = grid_get_dot(g, points, px, py + a);
926                     grid_face_set_dot(g, d, 0);
927                     d = grid_get_dot(g, points, px + a, py + a + b);
928                     grid_face_set_dot(g, d, 1);
929                     d = grid_get_dot(g, points, px - a, py + a + b);
930                     grid_face_set_dot(g, d, 2);
931                 }
932             }
933
934             /* generate left/right triangles */
935             if (y > 0) {
936                 grid_face_add_new(g, 3);
937                 if ((x + y) % 2) {
938                     d = grid_get_dot(g, points, px + a, py);
939                     grid_face_set_dot(g, d, 0);
940                     d = grid_get_dot(g, points, px + a + b, py - a);
941                     grid_face_set_dot(g, d, 1);
942                     d = grid_get_dot(g, points, px + a + b, py + a);
943                     grid_face_set_dot(g, d, 2);
944                 } else {
945                     d = grid_get_dot(g, points, px, py - a);
946                     grid_face_set_dot(g, d, 0);
947                     d = grid_get_dot(g, points, px + b, py);
948                     grid_face_set_dot(g, d, 1);
949                     d = grid_get_dot(g, points, px, py + a);
950                     grid_face_set_dot(g, d, 2);
951                 }
952             }
953         }
954     }
955
956     freetree234(points);
957     assert(g->num_faces <= max_faces);
958     assert(g->num_dots <= max_dots);
959     g->middle_face = g->faces + (height/2) * width + (width/2);
960
961     grid_make_consistent(g);
962     return g;
963 }
964
965 grid *grid_new_cairo(int width, int height)
966 {
967     int x, y;
968     /* Vector for side of pentagon - ratio is close to (4+sqrt(7))/3 */
969     int a = 14;
970     int b = 31;
971
972     /* Upper bounds - don't have to be exact */
973     int max_faces = 2 * width * height;
974     int max_dots = 3 * (width + 1) * (height + 1);
975     
976     tree234 *points;
977
978     grid *g = grid_new();
979     g->tilesize = 40;
980     g->faces = snewn(max_faces, grid_face);
981     g->dots = snewn(max_dots, grid_dot);
982
983     points = newtree234(grid_point_cmp_fn);
984
985     for (y = 0; y < height; y++) {
986         for (x = 0; x < width; x++) {
987             grid_dot *d;
988             /* cell position */
989             int px = 2 * b * x;
990             int py = 2 * b * y;
991
992             /* horizontal pentagons */
993             if (y > 0) {
994                 grid_face_add_new(g, 5);
995                 if ((x + y) % 2) {
996                     d = grid_get_dot(g, points, px + a, py - b);
997                     grid_face_set_dot(g, d, 0);
998                     d = grid_get_dot(g, points, px + 2*b - a, py - b);
999                     grid_face_set_dot(g, d, 1);
1000                     d = grid_get_dot(g, points, px + 2*b, py);
1001                     grid_face_set_dot(g, d, 2);
1002                     d = grid_get_dot(g, points, px + b, py + a);
1003                     grid_face_set_dot(g, d, 3);
1004                     d = grid_get_dot(g, points, px, py);
1005                     grid_face_set_dot(g, d, 4);
1006                 } else {
1007                     d = grid_get_dot(g, points, px, py);
1008                     grid_face_set_dot(g, d, 0);
1009                     d = grid_get_dot(g, points, px + b, py - a);
1010                     grid_face_set_dot(g, d, 1);
1011                     d = grid_get_dot(g, points, px + 2*b, py);
1012                     grid_face_set_dot(g, d, 2);
1013                     d = grid_get_dot(g, points, px + 2*b - a, py + b);
1014                     grid_face_set_dot(g, d, 3);
1015                     d = grid_get_dot(g, points, px + a, py + b);
1016                     grid_face_set_dot(g, d, 4);
1017                 }
1018             }
1019             /* vertical pentagons */
1020             if (x > 0) {
1021                 grid_face_add_new(g, 5);
1022                 if ((x + y) % 2) {
1023                     d = grid_get_dot(g, points, px, py);
1024                     grid_face_set_dot(g, d, 0);
1025                     d = grid_get_dot(g, points, px + b, py + a);
1026                     grid_face_set_dot(g, d, 1);
1027                     d = grid_get_dot(g, points, px + b, py + 2*b - a);
1028                     grid_face_set_dot(g, d, 2);
1029                     d = grid_get_dot(g, points, px, py + 2*b);
1030                     grid_face_set_dot(g, d, 3);
1031                     d = grid_get_dot(g, points, px - a, py + b);
1032                     grid_face_set_dot(g, d, 4);
1033                 } else {
1034                     d = grid_get_dot(g, points, px, py);
1035                     grid_face_set_dot(g, d, 0);
1036                     d = grid_get_dot(g, points, px + a, py + b);
1037                     grid_face_set_dot(g, d, 1);
1038                     d = grid_get_dot(g, points, px, py + 2*b);
1039                     grid_face_set_dot(g, d, 2);
1040                     d = grid_get_dot(g, points, px - b, py + 2*b - a);
1041                     grid_face_set_dot(g, d, 3);
1042                     d = grid_get_dot(g, points, px - b, py + a);
1043                     grid_face_set_dot(g, d, 4);
1044                 }
1045             }
1046         }
1047     }
1048
1049     freetree234(points);
1050     assert(g->num_faces <= max_faces);
1051     assert(g->num_dots <= max_dots);
1052     g->middle_face = g->faces + (height/2) * width + (width/2);
1053
1054     grid_make_consistent(g);
1055     return g;
1056 }
1057
1058 grid *grid_new_greathexagonal(int width, int height)
1059 {
1060     int x, y;
1061     /* Vector for side of triangle - ratio is close to sqrt(3) */
1062     int a = 15;
1063     int b = 26;
1064
1065     /* Upper bounds - don't have to be exact */
1066     int max_faces = 6 * (width + 1) * (height + 1);
1067     int max_dots = 6 * width * height;
1068
1069     tree234 *points;
1070
1071     grid *g = grid_new();
1072     g->tilesize = 18;
1073     g->faces = snewn(max_faces, grid_face);
1074     g->dots = snewn(max_dots, grid_dot);
1075
1076     points = newtree234(grid_point_cmp_fn);
1077
1078     for (y = 0; y < height; y++) {
1079         for (x = 0; x < width; x++) {
1080             grid_dot *d;
1081             /* centre of hexagon */
1082             int px = (3*a + b) * x;
1083             int py = (2*a + 2*b) * y;
1084             if (x % 2)
1085                 py += a + b;
1086
1087             /* hexagon */
1088             grid_face_add_new(g, 6);
1089             d = grid_get_dot(g, points, px - a, py - b);
1090             grid_face_set_dot(g, d, 0);
1091             d = grid_get_dot(g, points, px + a, py - b);
1092             grid_face_set_dot(g, d, 1);
1093             d = grid_get_dot(g, points, px + 2*a, py);
1094             grid_face_set_dot(g, d, 2);
1095             d = grid_get_dot(g, points, px + a, py + b);
1096             grid_face_set_dot(g, d, 3);
1097             d = grid_get_dot(g, points, px - a, py + b);
1098             grid_face_set_dot(g, d, 4);
1099             d = grid_get_dot(g, points, px - 2*a, py);
1100             grid_face_set_dot(g, d, 5);
1101
1102             /* square below hexagon */
1103             if (y < height - 1) {
1104                 grid_face_add_new(g, 4);
1105                 d = grid_get_dot(g, points, px - a, py + b);
1106                 grid_face_set_dot(g, d, 0);
1107                 d = grid_get_dot(g, points, px + a, py + b);
1108                 grid_face_set_dot(g, d, 1);
1109                 d = grid_get_dot(g, points, px + a, py + 2*a + b);
1110                 grid_face_set_dot(g, d, 2);
1111                 d = grid_get_dot(g, points, px - a, py + 2*a + b);
1112                 grid_face_set_dot(g, d, 3);
1113             }
1114
1115             /* square below right */
1116             if ((x < width - 1) && (((x % 2) == 0) || (y < height - 1))) {
1117                 grid_face_add_new(g, 4);
1118                 d = grid_get_dot(g, points, px + 2*a, py);
1119                 grid_face_set_dot(g, d, 0);
1120                 d = grid_get_dot(g, points, px + 2*a + b, py + a);
1121                 grid_face_set_dot(g, d, 1);
1122                 d = grid_get_dot(g, points, px + a + b, py + a + b);
1123                 grid_face_set_dot(g, d, 2);
1124                 d = grid_get_dot(g, points, px + a, py + b);
1125                 grid_face_set_dot(g, d, 3);
1126             }
1127
1128             /* square below left */
1129             if ((x > 0) && (((x % 2) == 0) || (y < height - 1))) {
1130                 grid_face_add_new(g, 4);
1131                 d = grid_get_dot(g, points, px - 2*a, py);
1132                 grid_face_set_dot(g, d, 0);
1133                 d = grid_get_dot(g, points, px - a, py + b);
1134                 grid_face_set_dot(g, d, 1);
1135                 d = grid_get_dot(g, points, px - a - b, py + a + b);
1136                 grid_face_set_dot(g, d, 2);
1137                 d = grid_get_dot(g, points, px - 2*a - b, py + a);
1138                 grid_face_set_dot(g, d, 3);
1139             }
1140            
1141             /* Triangle below right */
1142             if ((x < width - 1) && (y < height - 1)) {
1143                 grid_face_add_new(g, 3);
1144                 d = grid_get_dot(g, points, px + a, py + b);
1145                 grid_face_set_dot(g, d, 0);
1146                 d = grid_get_dot(g, points, px + a + b, py + a + b);
1147                 grid_face_set_dot(g, d, 1);
1148                 d = grid_get_dot(g, points, px + a, py + 2*a + b);
1149                 grid_face_set_dot(g, d, 2);
1150             }
1151
1152             /* Triangle below left */
1153             if ((x > 0) && (y < height - 1)) {
1154                 grid_face_add_new(g, 3);
1155                 d = grid_get_dot(g, points, px - a, py + b);
1156                 grid_face_set_dot(g, d, 0);
1157                 d = grid_get_dot(g, points, px - a, py + 2*a + b);
1158                 grid_face_set_dot(g, d, 1);
1159                 d = grid_get_dot(g, points, px - a - b, py + a + b);
1160                 grid_face_set_dot(g, d, 2);
1161             }
1162         }
1163     }
1164
1165     freetree234(points);
1166     assert(g->num_faces <= max_faces);
1167     assert(g->num_dots <= max_dots);
1168     g->middle_face = g->faces + (height/2) * width + (width/2);
1169
1170     grid_make_consistent(g);
1171     return g;
1172 }
1173
1174 grid *grid_new_octagonal(int width, int height)
1175 {
1176     int x, y;
1177     /* b/a approx sqrt(2) */
1178     int a = 29;
1179     int b = 41;
1180
1181     /* Upper bounds - don't have to be exact */
1182     int max_faces = 2 * width * height;
1183     int max_dots = 4 * (width + 1) * (height + 1);
1184
1185     tree234 *points;
1186
1187     grid *g = grid_new();
1188     g->tilesize = 40;
1189     g->faces = snewn(max_faces, grid_face);
1190     g->dots = snewn(max_dots, grid_dot);
1191
1192     points = newtree234(grid_point_cmp_fn);
1193
1194     for (y = 0; y < height; y++) {
1195         for (x = 0; x < width; x++) {
1196             grid_dot *d;
1197             /* cell position */
1198             int px = (2*a + b) * x;
1199             int py = (2*a + b) * y;
1200             /* octagon */
1201             grid_face_add_new(g, 8);
1202             d = grid_get_dot(g, points, px + a, py);
1203             grid_face_set_dot(g, d, 0);
1204             d = grid_get_dot(g, points, px + a + b, py);
1205             grid_face_set_dot(g, d, 1);
1206             d = grid_get_dot(g, points, px + 2*a + b, py + a);
1207             grid_face_set_dot(g, d, 2);
1208             d = grid_get_dot(g, points, px + 2*a + b, py + a + b);
1209             grid_face_set_dot(g, d, 3);
1210             d = grid_get_dot(g, points, px + a + b, py + 2*a + b);
1211             grid_face_set_dot(g, d, 4);
1212             d = grid_get_dot(g, points, px + a, py + 2*a + b);
1213             grid_face_set_dot(g, d, 5);
1214             d = grid_get_dot(g, points, px, py + a + b);
1215             grid_face_set_dot(g, d, 6);
1216             d = grid_get_dot(g, points, px, py + a);
1217             grid_face_set_dot(g, d, 7);
1218
1219             /* diamond */
1220             if ((x > 0) && (y > 0)) {
1221                 grid_face_add_new(g, 4);
1222                 d = grid_get_dot(g, points, px, py - a);
1223                 grid_face_set_dot(g, d, 0);
1224                 d = grid_get_dot(g, points, px + a, py);
1225                 grid_face_set_dot(g, d, 1);
1226                 d = grid_get_dot(g, points, px, py + a);
1227                 grid_face_set_dot(g, d, 2);
1228                 d = grid_get_dot(g, points, px - a, py);
1229                 grid_face_set_dot(g, d, 3);
1230             }
1231         }
1232     }
1233
1234     freetree234(points);
1235     assert(g->num_faces <= max_faces);
1236     assert(g->num_dots <= max_dots);
1237     g->middle_face = g->faces + (height/2) * width + (width/2);
1238
1239     grid_make_consistent(g);
1240     return g;
1241 }
1242
1243 grid *grid_new_kites(int width, int height)
1244 {
1245     int x, y;
1246     /* b/a approx sqrt(3) */
1247     int a = 15;
1248     int b = 26;
1249
1250     /* Upper bounds - don't have to be exact */
1251     int max_faces = 6 * width * height;
1252     int max_dots = 6 * (width + 1) * (height + 1);
1253
1254     tree234 *points;
1255
1256     grid *g = grid_new();
1257     g->tilesize = 40;
1258     g->faces = snewn(max_faces, grid_face);
1259     g->dots = snewn(max_dots, grid_dot);
1260
1261     points = newtree234(grid_point_cmp_fn);
1262
1263     for (y = 0; y < height; y++) {
1264         for (x = 0; x < width; x++) {
1265             grid_dot *d;
1266             /* position of order-6 dot */
1267             int px = 4*b * x;
1268             int py = 6*a * y;
1269             if (y % 2)
1270                 px += 2*b;
1271
1272             /* kite pointing up-left */
1273             grid_face_add_new(g, 4);
1274             d = grid_get_dot(g, points, px, py);
1275             grid_face_set_dot(g, d, 0);
1276             d = grid_get_dot(g, points, px + 2*b, py);
1277             grid_face_set_dot(g, d, 1);
1278             d = grid_get_dot(g, points, px + 2*b, py + 2*a);
1279             grid_face_set_dot(g, d, 2);
1280             d = grid_get_dot(g, points, px + b, py + 3*a);
1281             grid_face_set_dot(g, d, 3);
1282
1283             /* kite pointing up */
1284             grid_face_add_new(g, 4);
1285             d = grid_get_dot(g, points, px, py);
1286             grid_face_set_dot(g, d, 0);
1287             d = grid_get_dot(g, points, px + b, py + 3*a);
1288             grid_face_set_dot(g, d, 1);
1289             d = grid_get_dot(g, points, px, py + 4*a);
1290             grid_face_set_dot(g, d, 2);
1291             d = grid_get_dot(g, points, px - b, py + 3*a);
1292             grid_face_set_dot(g, d, 3);
1293
1294             /* kite pointing up-right */
1295             grid_face_add_new(g, 4);
1296             d = grid_get_dot(g, points, px, py);
1297             grid_face_set_dot(g, d, 0);
1298             d = grid_get_dot(g, points, px - b, py + 3*a);
1299             grid_face_set_dot(g, d, 1);
1300             d = grid_get_dot(g, points, px - 2*b, py + 2*a);
1301             grid_face_set_dot(g, d, 2);
1302             d = grid_get_dot(g, points, px - 2*b, py);
1303             grid_face_set_dot(g, d, 3);
1304
1305             /* kite pointing down-right */
1306             grid_face_add_new(g, 4);
1307             d = grid_get_dot(g, points, px, py);
1308             grid_face_set_dot(g, d, 0);
1309             d = grid_get_dot(g, points, px - 2*b, py);
1310             grid_face_set_dot(g, d, 1);
1311             d = grid_get_dot(g, points, px - 2*b, py - 2*a);
1312             grid_face_set_dot(g, d, 2);
1313             d = grid_get_dot(g, points, px - b, py - 3*a);
1314             grid_face_set_dot(g, d, 3);
1315
1316             /* kite pointing down */
1317             grid_face_add_new(g, 4);
1318             d = grid_get_dot(g, points, px, py);
1319             grid_face_set_dot(g, d, 0);
1320             d = grid_get_dot(g, points, px - b, py - 3*a);
1321             grid_face_set_dot(g, d, 1);
1322             d = grid_get_dot(g, points, px, py - 4*a);
1323             grid_face_set_dot(g, d, 2);
1324             d = grid_get_dot(g, points, px + b, py - 3*a);
1325             grid_face_set_dot(g, d, 3);
1326
1327             /* kite pointing down-left */
1328             grid_face_add_new(g, 4);
1329             d = grid_get_dot(g, points, px, py);
1330             grid_face_set_dot(g, d, 0);
1331             d = grid_get_dot(g, points, px + b, py - 3*a);
1332             grid_face_set_dot(g, d, 1);
1333             d = grid_get_dot(g, points, px + 2*b, py - 2*a);
1334             grid_face_set_dot(g, d, 2);
1335             d = grid_get_dot(g, points, px + 2*b, py);
1336             grid_face_set_dot(g, d, 3);
1337         }
1338     }
1339
1340     freetree234(points);
1341     assert(g->num_faces <= max_faces);
1342     assert(g->num_dots <= max_dots);
1343     g->middle_face = g->faces + 6 * ((height/2) * width + (width/2));
1344
1345     grid_make_consistent(g);
1346     return g;
1347 }
1348
1349 /* ----------- End of grid generators ------------- */