24380d911ea0ec7750a14da5bc7b74b4b1d5f73f
[sgt/puzzles] / 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 #include <float.h>
16
17 #include "puzzles.h"
18 #include "tree234.h"
19 #include "grid.h"
20 #include "penrose.h"
21
22 /* Debugging options */
23
24 /*
25 #define DEBUG_GRID
26 */
27
28 /* ----------------------------------------------------------------------
29 * Deallocate or dereference a grid
30 */
31 void grid_free(grid *g)
32 {
33 assert(g->refcount);
34
35 g->refcount--;
36 if (g->refcount == 0) {
37 int i;
38 for (i = 0; i < g->num_faces; i++) {
39 sfree(g->faces[i].dots);
40 sfree(g->faces[i].edges);
41 }
42 for (i = 0; i < g->num_dots; i++) {
43 sfree(g->dots[i].faces);
44 sfree(g->dots[i].edges);
45 }
46 sfree(g->faces);
47 sfree(g->edges);
48 sfree(g->dots);
49 sfree(g);
50 }
51 }
52
53 /* Used by the other grid generators. Create a brand new grid with nothing
54 * initialised (all lists are NULL) */
55 static grid *grid_empty(void)
56 {
57 grid *g = snew(grid);
58 g->faces = NULL;
59 g->edges = NULL;
60 g->dots = NULL;
61 g->num_faces = g->num_edges = g->num_dots = 0;
62 g->refcount = 1;
63 g->lowest_x = g->lowest_y = g->highest_x = g->highest_y = 0;
64 return g;
65 }
66
67 /* Helper function to calculate perpendicular distance from
68 * a point P to a line AB. A and B mustn't be equal here.
69 *
70 * Well-known formula for area A of a triangle:
71 * / 1 1 1 \
72 * 2A = determinant of matrix | px ax bx |
73 * \ py ay by /
74 *
75 * Also well-known: 2A = base * height
76 * = perpendicular distance * line-length.
77 *
78 * Combining gives: distance = determinant / line-length(a,b)
79 */
80 static double point_line_distance(long px, long py,
81 long ax, long ay,
82 long bx, long by)
83 {
84 long det = ax*by - bx*ay + bx*py - px*by + px*ay - ax*py;
85 double len;
86 det = max(det, -det);
87 len = sqrt(SQ(ax - bx) + SQ(ay - by));
88 return det / len;
89 }
90
91 /* Determine nearest edge to where the user clicked.
92 * (x, y) is the clicked location, converted to grid coordinates.
93 * Returns the nearest edge, or NULL if no edge is reasonably
94 * near the position.
95 *
96 * Just judging edges by perpendicular distance is not quite right -
97 * the edge might be "off to one side". So we insist that the triangle
98 * with (x,y) has acute angles at the edge's dots.
99 *
100 * edge1
101 * *---------*------
102 * |
103 * | *(x,y)
104 * edge2 |
105 * | edge2 is OK, but edge1 is not, even though
106 * | edge1 is perpendicularly closer to (x,y)
107 * *
108 *
109 */
110 grid_edge *grid_nearest_edge(grid *g, int x, int y)
111 {
112 grid_edge *best_edge;
113 double best_distance = 0;
114 int i;
115
116 best_edge = NULL;
117
118 for (i = 0; i < g->num_edges; i++) {
119 grid_edge *e = &g->edges[i];
120 long e2; /* squared length of edge */
121 long a2, b2; /* squared lengths of other sides */
122 double dist;
123
124 /* See if edge e is eligible - the triangle must have acute angles
125 * at the edge's dots.
126 * Pythagoras formula h^2 = a^2 + b^2 detects right-angles,
127 * so detect acute angles by testing for h^2 < a^2 + b^2 */
128 e2 = SQ((long)e->dot1->x - (long)e->dot2->x) + SQ((long)e->dot1->y - (long)e->dot2->y);
129 a2 = SQ((long)e->dot1->x - (long)x) + SQ((long)e->dot1->y - (long)y);
130 b2 = SQ((long)e->dot2->x - (long)x) + SQ((long)e->dot2->y - (long)y);
131 if (a2 >= e2 + b2) continue;
132 if (b2 >= e2 + a2) continue;
133
134 /* e is eligible so far. Now check the edge is reasonably close
135 * to where the user clicked. Don't want to toggle an edge if the
136 * click was way off the grid.
137 * There is room for experimentation here. We could check the
138 * perpendicular distance is within a certain fraction of the length
139 * of the edge. That amounts to testing a rectangular region around
140 * the edge.
141 * Alternatively, we could check that the angle at the point is obtuse.
142 * That would amount to testing a circular region with the edge as
143 * diameter. */
144 dist = point_line_distance((long)x, (long)y,
145 (long)e->dot1->x, (long)e->dot1->y,
146 (long)e->dot2->x, (long)e->dot2->y);
147 /* Is dist more than half edge length ? */
148 if (4 * SQ(dist) > e2)
149 continue;
150
151 if (best_edge == NULL || dist < best_distance) {
152 best_edge = e;
153 best_distance = dist;
154 }
155 }
156 return best_edge;
157 }
158
159 /* ----------------------------------------------------------------------
160 * Grid generation
161 */
162
163 #ifdef SVG_GRID
164
165 #define SVG_DOTS 1
166 #define SVG_EDGES 2
167 #define SVG_FACES 4
168
169 #define FACE_COLOUR "red"
170 #define EDGE_COLOUR "blue"
171 #define DOT_COLOUR "black"
172
173 static void grid_output_svg(FILE *fp, grid *g, int which)
174 {
175 int i, j;
176
177 fprintf(fp,"\
178 <?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n\
179 <!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n\
180 \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n\
181 \n\
182 <svg xmlns=\"http://www.w3.org/2000/svg\"\n\
183 xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n\n");
184
185 if (which & SVG_FACES) {
186 fprintf(fp, "<g>\n");
187 for (i = 0; i < g->num_faces; i++) {
188 grid_face *f = g->faces + i;
189 fprintf(fp, "<polygon points=\"");
190 for (j = 0; j < f->order; j++) {
191 grid_dot *d = f->dots[j];
192 fprintf(fp, "%s%d,%d", (j == 0) ? "" : " ",
193 d->x, d->y);
194 }
195 fprintf(fp, "\" style=\"fill: %s; fill-opacity: 0.2; stroke: %s\" />\n",
196 FACE_COLOUR, FACE_COLOUR);
197 }
198 fprintf(fp, "</g>\n");
199 }
200 if (which & SVG_EDGES) {
201 fprintf(fp, "<g>\n");
202 for (i = 0; i < g->num_edges; i++) {
203 grid_edge *e = g->edges + i;
204 grid_dot *d1 = e->dot1, *d2 = e->dot2;
205
206 fprintf(fp, "<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" "
207 "style=\"stroke: %s\" />\n",
208 d1->x, d1->y, d2->x, d2->y, EDGE_COLOUR);
209 }
210 fprintf(fp, "</g>\n");
211 }
212
213 if (which & SVG_DOTS) {
214 fprintf(fp, "<g>\n");
215 for (i = 0; i < g->num_dots; i++) {
216 grid_dot *d = g->dots + i;
217 fprintf(fp, "<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" fill=\"%s\" />",
218 d->x, d->y, g->tilesize/20, g->tilesize/20, DOT_COLOUR);
219 }
220 fprintf(fp, "</g>\n");
221 }
222
223 fprintf(fp, "</svg>\n");
224 }
225 #endif
226
227 #ifdef SVG_GRID
228 #include <errno.h>
229
230 static void grid_try_svg(grid *g, int which)
231 {
232 char *svg = getenv("PUZZLES_SVG_GRID");
233 if (svg) {
234 FILE *svgf = fopen(svg, "w");
235 if (svgf) {
236 grid_output_svg(svgf, g, which);
237 fclose(svgf);
238 } else {
239 fprintf(stderr, "Unable to open file `%s': %s", svg, strerror(errno));
240 }
241 }
242 }
243 #endif
244
245 /* Show the basic grid information, before doing grid_make_consistent */
246 static void grid_debug_basic(grid *g)
247 {
248 /* TODO: Maybe we should generate an SVG image of the dots and lines
249 * of the grid here, before grid_make_consistent.
250 * Would help with debugging grid generation. */
251 #ifdef DEBUG_GRID
252 int i;
253 printf("--- Basic Grid Data ---\n");
254 for (i = 0; i < g->num_faces; i++) {
255 grid_face *f = g->faces + i;
256 printf("Face %d: dots[", i);
257 int j;
258 for (j = 0; j < f->order; j++) {
259 grid_dot *d = f->dots[j];
260 printf("%s%d", j ? "," : "", (int)(d - g->dots));
261 }
262 printf("]\n");
263 }
264 #endif
265 #ifdef SVG_GRID
266 grid_try_svg(g, SVG_FACES);
267 #endif
268 }
269
270 /* Show the derived grid information, computed by grid_make_consistent */
271 static void grid_debug_derived(grid *g)
272 {
273 #ifdef DEBUG_GRID
274 /* edges */
275 int i;
276 printf("--- Derived Grid Data ---\n");
277 for (i = 0; i < g->num_edges; i++) {
278 grid_edge *e = g->edges + i;
279 printf("Edge %d: dots[%d,%d] faces[%d,%d]\n",
280 i, (int)(e->dot1 - g->dots), (int)(e->dot2 - g->dots),
281 e->face1 ? (int)(e->face1 - g->faces) : -1,
282 e->face2 ? (int)(e->face2 - g->faces) : -1);
283 }
284 /* faces */
285 for (i = 0; i < g->num_faces; i++) {
286 grid_face *f = g->faces + i;
287 int j;
288 printf("Face %d: faces[", i);
289 for (j = 0; j < f->order; j++) {
290 grid_edge *e = f->edges[j];
291 grid_face *f2 = (e->face1 == f) ? e->face2 : e->face1;
292 printf("%s%d", j ? "," : "", f2 ? (int)(f2 - g->faces) : -1);
293 }
294 printf("]\n");
295 }
296 /* dots */
297 for (i = 0; i < g->num_dots; i++) {
298 grid_dot *d = g->dots + i;
299 int j;
300 printf("Dot %d: dots[", i);
301 for (j = 0; j < d->order; j++) {
302 grid_edge *e = d->edges[j];
303 grid_dot *d2 = (e->dot1 == d) ? e->dot2 : e->dot1;
304 printf("%s%d", j ? "," : "", (int)(d2 - g->dots));
305 }
306 printf("] faces[");
307 for (j = 0; j < d->order; j++) {
308 grid_face *f = d->faces[j];
309 printf("%s%d", j ? "," : "", f ? (int)(f - g->faces) : -1);
310 }
311 printf("]\n");
312 }
313 #endif
314 #ifdef SVG_GRID
315 grid_try_svg(g, SVG_DOTS | SVG_EDGES | SVG_FACES);
316 #endif
317 }
318
319 /* Helper function for building incomplete-edges list in
320 * grid_make_consistent() */
321 static int grid_edge_bydots_cmpfn(void *v1, void *v2)
322 {
323 grid_edge *a = v1;
324 grid_edge *b = v2;
325 grid_dot *da, *db;
326
327 /* Pointer subtraction is valid here, because all dots point into the
328 * same dot-list (g->dots).
329 * Edges are not "normalised" - the 2 dots could be stored in any order,
330 * so we need to take this into account when comparing edges. */
331
332 /* Compare first dots */
333 da = (a->dot1 < a->dot2) ? a->dot1 : a->dot2;
334 db = (b->dot1 < b->dot2) ? b->dot1 : b->dot2;
335 if (da != db)
336 return db - da;
337 /* Compare last dots */
338 da = (a->dot1 < a->dot2) ? a->dot2 : a->dot1;
339 db = (b->dot1 < b->dot2) ? b->dot2 : b->dot1;
340 if (da != db)
341 return db - da;
342
343 return 0;
344 }
345
346 /*
347 * 'Vigorously trim' a grid, by which I mean deleting any isolated or
348 * uninteresting faces. By which, in turn, I mean: ensure that the
349 * grid is composed solely of faces adjacent to at least one
350 * 'landlocked' dot (i.e. one not in contact with the infinite
351 * exterior face), and that all those dots are in a single connected
352 * component.
353 *
354 * This function operates on, and returns, a grid satisfying the
355 * preconditions to grid_make_consistent() rather than the
356 * postconditions. (So call it first.)
357 */
358 static void grid_trim_vigorously(grid *g)
359 {
360 int *dotpairs, *faces, *dots;
361 int *dsf;
362 int i, j, k, size, newfaces, newdots;
363
364 /*
365 * First construct a matrix in which each ordered pair of dots is
366 * mapped to the index of the face in which those dots occur in
367 * that order.
368 */
369 dotpairs = snewn(g->num_dots * g->num_dots, int);
370 for (i = 0; i < g->num_dots; i++)
371 for (j = 0; j < g->num_dots; j++)
372 dotpairs[i*g->num_dots+j] = -1;
373 for (i = 0; i < g->num_faces; i++) {
374 grid_face *f = g->faces + i;
375 int dot0 = f->dots[f->order-1] - g->dots;
376 for (j = 0; j < f->order; j++) {
377 int dot1 = f->dots[j] - g->dots;
378 dotpairs[dot0 * g->num_dots + dot1] = i;
379 dot0 = dot1;
380 }
381 }
382
383 /*
384 * Now we can identify landlocked dots: they're the ones all of
385 * whose edges have a mirror-image counterpart in this matrix.
386 */
387 dots = snewn(g->num_dots, int);
388 for (i = 0; i < g->num_dots; i++) {
389 dots[i] = TRUE;
390 for (j = 0; j < g->num_dots; j++) {
391 if ((dotpairs[i*g->num_dots+j] >= 0) ^
392 (dotpairs[j*g->num_dots+i] >= 0))
393 dots[i] = FALSE; /* non-duplicated edge: coastal dot */
394 }
395 }
396
397 /*
398 * Now identify connected pairs of landlocked dots, and form a dsf
399 * unifying them.
400 */
401 dsf = snew_dsf(g->num_dots);
402 for (i = 0; i < g->num_dots; i++)
403 for (j = 0; j < i; j++)
404 if (dots[i] && dots[j] &&
405 dotpairs[i*g->num_dots+j] >= 0 &&
406 dotpairs[j*g->num_dots+i] >= 0)
407 dsf_merge(dsf, i, j);
408
409 /*
410 * Now look for the largest component.
411 */
412 size = 0;
413 j = -1;
414 for (i = 0; i < g->num_dots; i++) {
415 int newsize;
416 if (dots[i] && dsf_canonify(dsf, i) == i &&
417 (newsize = dsf_size(dsf, i)) > size) {
418 j = i;
419 size = newsize;
420 }
421 }
422
423 /*
424 * Work out which faces we're going to keep (precisely those with
425 * at least one dot in the same connected component as j) and
426 * which dots (those required by any face we're keeping).
427 *
428 * At this point we reuse the 'dots' array to indicate the dots
429 * we're keeping, rather than the ones that are landlocked.
430 */
431 faces = snewn(g->num_faces, int);
432 for (i = 0; i < g->num_faces; i++)
433 faces[i] = 0;
434 for (i = 0; i < g->num_dots; i++)
435 dots[i] = 0;
436 for (i = 0; i < g->num_faces; i++) {
437 grid_face *f = g->faces + i;
438 int keep = FALSE;
439 for (k = 0; k < f->order; k++)
440 if (dsf_canonify(dsf, f->dots[k] - g->dots) == j)
441 keep = TRUE;
442 if (keep) {
443 faces[i] = TRUE;
444 for (k = 0; k < f->order; k++)
445 dots[f->dots[k]-g->dots] = TRUE;
446 }
447 }
448
449 /*
450 * Work out the new indices of those faces and dots, when we
451 * compact the arrays containing them.
452 */
453 for (i = newfaces = 0; i < g->num_faces; i++)
454 faces[i] = (faces[i] ? newfaces++ : -1);
455 for (i = newdots = 0; i < g->num_dots; i++)
456 dots[i] = (dots[i] ? newdots++ : -1);
457
458 /*
459 * Free the dynamically allocated 'dots' pointer lists in faces
460 * we're going to discard.
461 */
462 for (i = 0; i < g->num_faces; i++)
463 if (faces[i] < 0)
464 sfree(g->faces[i].dots);
465
466 /*
467 * Go through and compact the arrays.
468 */
469 for (i = 0; i < g->num_dots; i++)
470 if (dots[i] >= 0) {
471 grid_dot *dnew = g->dots + dots[i], *dold = g->dots + i;
472 *dnew = *dold; /* structure copy */
473 }
474 for (i = 0; i < g->num_faces; i++)
475 if (faces[i] >= 0) {
476 grid_face *fnew = g->faces + faces[i], *fold = g->faces + i;
477 *fnew = *fold; /* structure copy */
478 for (j = 0; j < fnew->order; j++) {
479 /*
480 * Reindex the dots in this face.
481 */
482 k = fnew->dots[j] - g->dots;
483 fnew->dots[j] = g->dots + dots[k];
484 }
485 }
486 g->num_faces = newfaces;
487 g->num_dots = newdots;
488
489 sfree(dotpairs);
490 sfree(dsf);
491 sfree(dots);
492 sfree(faces);
493 }
494
495 /* Input: grid has its dots and faces initialised:
496 * - dots have (optionally) x and y coordinates, but no edges or faces
497 * (pointers are NULL).
498 * - edges not initialised at all
499 * - faces initialised and know which dots they have (but no edges yet). The
500 * dots around each face are assumed to be clockwise.
501 *
502 * Output: grid is complete and valid with all relationships defined.
503 */
504 static void grid_make_consistent(grid *g)
505 {
506 int i;
507 tree234 *incomplete_edges;
508 grid_edge *next_new_edge; /* Where new edge will go into g->edges */
509
510 grid_debug_basic(g);
511
512 /* ====== Stage 1 ======
513 * Generate edges
514 */
515
516 /* We know how many dots and faces there are, so we can find the exact
517 * number of edges from Euler's polyhedral formula: F + V = E + 2 .
518 * We use "-1", not "-2" here, because Euler's formula includes the
519 * infinite face, which we don't count. */
520 g->num_edges = g->num_faces + g->num_dots - 1;
521 debug(("allocating room for %d edges\n", g->num_edges));
522 g->edges = snewn(g->num_edges, grid_edge);
523 next_new_edge = g->edges;
524
525 /* Iterate over faces, and over each face's dots, generating edges as we
526 * go. As we find each new edge, we can immediately fill in the edge's
527 * dots, but only one of the edge's faces. Later on in the iteration, we
528 * will find the same edge again (unless it's on the border), but we will
529 * know the other face.
530 * For efficiency, maintain a list of the incomplete edges, sorted by
531 * their dots. */
532 incomplete_edges = newtree234(grid_edge_bydots_cmpfn);
533 for (i = 0; i < g->num_faces; i++) {
534 grid_face *f = g->faces + i;
535 int j;
536 assert(f->order > 2);
537 for (j = 0; j < f->order; j++) {
538 grid_edge e; /* fake edge for searching */
539 grid_edge *edge_found;
540 int j2 = j + 1;
541 if (j2 == f->order)
542 j2 = 0;
543 e.dot1 = f->dots[j];
544 e.dot2 = f->dots[j2];
545 /* Use del234 instead of find234, because we always want to
546 * remove the edge if found */
547 edge_found = del234(incomplete_edges, &e);
548 if (edge_found) {
549 /* This edge already added, so fill out missing face.
550 * Edge is already removed from incomplete_edges. */
551 edge_found->face2 = f;
552 } else {
553 assert(next_new_edge - g->edges < g->num_edges);
554 next_new_edge->dot1 = e.dot1;
555 next_new_edge->dot2 = e.dot2;
556 next_new_edge->face1 = f;
557 next_new_edge->face2 = NULL; /* potentially infinite face */
558 add234(incomplete_edges, next_new_edge);
559 ++next_new_edge;
560 }
561 }
562 }
563 freetree234(incomplete_edges);
564
565 /* ====== Stage 2 ======
566 * For each face, build its edge list.
567 */
568
569 /* Allocate space for each edge list. Can do this, because each face's
570 * edge-list is the same size as its dot-list. */
571 for (i = 0; i < g->num_faces; i++) {
572 grid_face *f = g->faces + i;
573 int j;
574 f->edges = snewn(f->order, grid_edge*);
575 /* Preload with NULLs, to help detect potential bugs. */
576 for (j = 0; j < f->order; j++)
577 f->edges[j] = NULL;
578 }
579
580 /* Iterate over each edge, and over both its faces. Add this edge to
581 * the face's edge-list, after finding where it should go in the
582 * sequence. */
583 for (i = 0; i < g->num_edges; i++) {
584 grid_edge *e = g->edges + i;
585 int j;
586 for (j = 0; j < 2; j++) {
587 grid_face *f = j ? e->face2 : e->face1;
588 int k, k2;
589 if (f == NULL) continue;
590 /* Find one of the dots around the face */
591 for (k = 0; k < f->order; k++) {
592 if (f->dots[k] == e->dot1)
593 break; /* found dot1 */
594 }
595 assert(k != f->order); /* Must find the dot around this face */
596
597 /* Labelling scheme: as we walk clockwise around the face,
598 * starting at dot0 (f->dots[0]), we hit:
599 * (dot0), edge0, dot1, edge1, dot2,...
600 *
601 * 0
602 * 0-----1
603 * |
604 * |1
605 * |
606 * 3-----2
607 * 2
608 *
609 * Therefore, edgeK joins dotK and dot{K+1}
610 */
611
612 /* Around this face, either the next dot or the previous dot
613 * must be e->dot2. Otherwise the edge is wrong. */
614 k2 = k + 1;
615 if (k2 == f->order)
616 k2 = 0;
617 if (f->dots[k2] == e->dot2) {
618 /* dot1(k) and dot2(k2) go clockwise around this face, so add
619 * this edge at position k (see diagram). */
620 assert(f->edges[k] == NULL);
621 f->edges[k] = e;
622 continue;
623 }
624 /* Try previous dot */
625 k2 = k - 1;
626 if (k2 == -1)
627 k2 = f->order - 1;
628 if (f->dots[k2] == e->dot2) {
629 /* dot1(k) and dot2(k2) go anticlockwise around this face. */
630 assert(f->edges[k2] == NULL);
631 f->edges[k2] = e;
632 continue;
633 }
634 assert(!"Grid broken: bad edge-face relationship");
635 }
636 }
637
638 /* ====== Stage 3 ======
639 * For each dot, build its edge-list and face-list.
640 */
641
642 /* We don't know how many edges/faces go around each dot, so we can't
643 * allocate the right space for these lists. Pre-compute the sizes by
644 * iterating over each edge and recording a tally against each dot. */
645 for (i = 0; i < g->num_dots; i++) {
646 g->dots[i].order = 0;
647 }
648 for (i = 0; i < g->num_edges; i++) {
649 grid_edge *e = g->edges + i;
650 ++(e->dot1->order);
651 ++(e->dot2->order);
652 }
653 /* Now we have the sizes, pre-allocate the edge and face lists. */
654 for (i = 0; i < g->num_dots; i++) {
655 grid_dot *d = g->dots + i;
656 int j;
657 assert(d->order >= 2); /* sanity check */
658 d->edges = snewn(d->order, grid_edge*);
659 d->faces = snewn(d->order, grid_face*);
660 for (j = 0; j < d->order; j++) {
661 d->edges[j] = NULL;
662 d->faces[j] = NULL;
663 }
664 }
665 /* For each dot, need to find a face that touches it, so we can seed
666 * the edge-face-edge-face process around each dot. */
667 for (i = 0; i < g->num_faces; i++) {
668 grid_face *f = g->faces + i;
669 int j;
670 for (j = 0; j < f->order; j++) {
671 grid_dot *d = f->dots[j];
672 d->faces[0] = f;
673 }
674 }
675 /* Each dot now has a face in its first slot. Generate the remaining
676 * faces and edges around the dot, by searching both clockwise and
677 * anticlockwise from the first face. Need to do both directions,
678 * because of the possibility of hitting the infinite face, which
679 * blocks progress. But there's only one such face, so we will
680 * succeed in finding every edge and face this way. */
681 for (i = 0; i < g->num_dots; i++) {
682 grid_dot *d = g->dots + i;
683 int current_face1 = 0; /* ascends clockwise */
684 int current_face2 = 0; /* descends anticlockwise */
685
686 /* Labelling scheme: as we walk clockwise around the dot, starting
687 * at face0 (d->faces[0]), we hit:
688 * (face0), edge0, face1, edge1, face2,...
689 *
690 * 0
691 * |
692 * 0 | 1
693 * |
694 * -----d-----1
695 * |
696 * | 2
697 * |
698 * 2
699 *
700 * So, for example, face1 should be joined to edge0 and edge1,
701 * and those edges should appear in an anticlockwise sense around
702 * that face (see diagram). */
703
704 /* clockwise search */
705 while (TRUE) {
706 grid_face *f = d->faces[current_face1];
707 grid_edge *e;
708 int j;
709 assert(f != NULL);
710 /* find dot around this face */
711 for (j = 0; j < f->order; j++) {
712 if (f->dots[j] == d)
713 break;
714 }
715 assert(j != f->order); /* must find dot */
716
717 /* Around f, required edge is anticlockwise from the dot. See
718 * the other labelling scheme higher up, for why we subtract 1
719 * from j. */
720 j--;
721 if (j == -1)
722 j = f->order - 1;
723 e = f->edges[j];
724 d->edges[current_face1] = e; /* set edge */
725 current_face1++;
726 if (current_face1 == d->order)
727 break;
728 else {
729 /* set face */
730 d->faces[current_face1] =
731 (e->face1 == f) ? e->face2 : e->face1;
732 if (d->faces[current_face1] == NULL)
733 break; /* cannot progress beyond infinite face */
734 }
735 }
736 /* If the clockwise search made it all the way round, don't need to
737 * bother with the anticlockwise search. */
738 if (current_face1 == d->order)
739 continue; /* this dot is complete, move on to next dot */
740
741 /* anticlockwise search */
742 while (TRUE) {
743 grid_face *f = d->faces[current_face2];
744 grid_edge *e;
745 int j;
746 assert(f != NULL);
747 /* find dot around this face */
748 for (j = 0; j < f->order; j++) {
749 if (f->dots[j] == d)
750 break;
751 }
752 assert(j != f->order); /* must find dot */
753
754 /* Around f, required edge is clockwise from the dot. */
755 e = f->edges[j];
756
757 current_face2--;
758 if (current_face2 == -1)
759 current_face2 = d->order - 1;
760 d->edges[current_face2] = e; /* set edge */
761
762 /* set face */
763 if (current_face2 == current_face1)
764 break;
765 d->faces[current_face2] =
766 (e->face1 == f) ? e->face2 : e->face1;
767 /* There's only 1 infinite face, so we must get all the way
768 * to current_face1 before we hit it. */
769 assert(d->faces[current_face2]);
770 }
771 }
772
773 /* ====== Stage 4 ======
774 * Compute other grid settings
775 */
776
777 /* Bounding rectangle */
778 for (i = 0; i < g->num_dots; i++) {
779 grid_dot *d = g->dots + i;
780 if (i == 0) {
781 g->lowest_x = g->highest_x = d->x;
782 g->lowest_y = g->highest_y = d->y;
783 } else {
784 g->lowest_x = min(g->lowest_x, d->x);
785 g->highest_x = max(g->highest_x, d->x);
786 g->lowest_y = min(g->lowest_y, d->y);
787 g->highest_y = max(g->highest_y, d->y);
788 }
789 }
790
791 grid_debug_derived(g);
792 }
793
794 /* Helpers for making grid-generation easier. These functions are only
795 * intended for use during grid generation. */
796
797 /* Comparison function for the (tree234) sorted dot list */
798 static int grid_point_cmp_fn(void *v1, void *v2)
799 {
800 grid_dot *p1 = v1;
801 grid_dot *p2 = v2;
802 if (p1->y != p2->y)
803 return p2->y - p1->y;
804 else
805 return p2->x - p1->x;
806 }
807 /* Add a new face to the grid, with its dot list allocated.
808 * Assumes there's enough space allocated for the new face in grid->faces */
809 static void grid_face_add_new(grid *g, int face_size)
810 {
811 int i;
812 grid_face *new_face = g->faces + g->num_faces;
813 new_face->order = face_size;
814 new_face->dots = snewn(face_size, grid_dot*);
815 for (i = 0; i < face_size; i++)
816 new_face->dots[i] = NULL;
817 new_face->edges = NULL;
818 new_face->has_incentre = FALSE;
819 g->num_faces++;
820 }
821 /* Assumes dot list has enough space */
822 static grid_dot *grid_dot_add_new(grid *g, int x, int y)
823 {
824 grid_dot *new_dot = g->dots + g->num_dots;
825 new_dot->order = 0;
826 new_dot->edges = NULL;
827 new_dot->faces = NULL;
828 new_dot->x = x;
829 new_dot->y = y;
830 g->num_dots++;
831 return new_dot;
832 }
833 /* Retrieve a dot with these (x,y) coordinates. Either return an existing dot
834 * in the dot_list, or add a new dot to the grid (and the dot_list) and
835 * return that.
836 * Assumes g->dots has enough capacity allocated */
837 static grid_dot *grid_get_dot(grid *g, tree234 *dot_list, int x, int y)
838 {
839 grid_dot test, *ret;
840
841 test.order = 0;
842 test.edges = NULL;
843 test.faces = NULL;
844 test.x = x;
845 test.y = y;
846 ret = find234(dot_list, &test, NULL);
847 if (ret)
848 return ret;
849
850 ret = grid_dot_add_new(g, x, y);
851 add234(dot_list, ret);
852 return ret;
853 }
854
855 /* Sets the last face of the grid to include this dot, at this position
856 * around the face. Assumes num_faces is at least 1 (a new face has
857 * previously been added, with the required number of dots allocated) */
858 static void grid_face_set_dot(grid *g, grid_dot *d, int position)
859 {
860 grid_face *last_face = g->faces + g->num_faces - 1;
861 last_face->dots[position] = d;
862 }
863
864 /*
865 * Helper routines for grid_find_incentre.
866 */
867 static int solve_2x2_matrix(double mx[4], double vin[2], double vout[2])
868 {
869 double inv[4];
870 double det;
871 det = (mx[0]*mx[3] - mx[1]*mx[2]);
872 if (det == 0)
873 return FALSE;
874
875 inv[0] = mx[3] / det;
876 inv[1] = -mx[1] / det;
877 inv[2] = -mx[2] / det;
878 inv[3] = mx[0] / det;
879
880 vout[0] = inv[0]*vin[0] + inv[1]*vin[1];
881 vout[1] = inv[2]*vin[0] + inv[3]*vin[1];
882
883 return TRUE;
884 }
885 static int solve_3x3_matrix(double mx[9], double vin[3], double vout[3])
886 {
887 double inv[9];
888 double det;
889
890 det = (mx[0]*mx[4]*mx[8] + mx[1]*mx[5]*mx[6] + mx[2]*mx[3]*mx[7] -
891 mx[0]*mx[5]*mx[7] - mx[1]*mx[3]*mx[8] - mx[2]*mx[4]*mx[6]);
892 if (det == 0)
893 return FALSE;
894
895 inv[0] = (mx[4]*mx[8] - mx[5]*mx[7]) / det;
896 inv[1] = (mx[2]*mx[7] - mx[1]*mx[8]) / det;
897 inv[2] = (mx[1]*mx[5] - mx[2]*mx[4]) / det;
898 inv[3] = (mx[5]*mx[6] - mx[3]*mx[8]) / det;
899 inv[4] = (mx[0]*mx[8] - mx[2]*mx[6]) / det;
900 inv[5] = (mx[2]*mx[3] - mx[0]*mx[5]) / det;
901 inv[6] = (mx[3]*mx[7] - mx[4]*mx[6]) / det;
902 inv[7] = (mx[1]*mx[6] - mx[0]*mx[7]) / det;
903 inv[8] = (mx[0]*mx[4] - mx[1]*mx[3]) / det;
904
905 vout[0] = inv[0]*vin[0] + inv[1]*vin[1] + inv[2]*vin[2];
906 vout[1] = inv[3]*vin[0] + inv[4]*vin[1] + inv[5]*vin[2];
907 vout[2] = inv[6]*vin[0] + inv[7]*vin[1] + inv[8]*vin[2];
908
909 return TRUE;
910 }
911
912 void grid_find_incentre(grid_face *f)
913 {
914 double xbest, ybest, bestdist;
915 int i, j, k, m;
916 grid_dot *edgedot1[3], *edgedot2[3];
917 grid_dot *dots[3];
918 int nedges, ndots;
919
920 if (f->has_incentre)
921 return;
922
923 /*
924 * Find the point in the polygon with the maximum distance to any
925 * edge or corner.
926 *
927 * Such a point must exist which is in contact with at least three
928 * edges and/or vertices. (Proof: if it's only in contact with two
929 * edges and/or vertices, it can't even be at a _local_ maximum -
930 * any such circle can always be expanded in some direction.) So
931 * we iterate through all 3-subsets of the combined set of edges
932 * and vertices; for each subset we generate one or two candidate
933 * points that might be the incentre, and then we vet each one to
934 * see if it's inside the polygon and what its maximum radius is.
935 *
936 * (There's one case which this algorithm will get noticeably
937 * wrong, and that's when a continuum of equally good answers
938 * exists due to parallel edges. Consider a long thin rectangle,
939 * for instance, or a parallelogram. This algorithm will pick a
940 * point near one end, and choose the end arbitrarily; obviously a
941 * nicer point to choose would be in the centre. To fix this I
942 * would have to introduce a special-case system which detected
943 * parallel edges in advance, set aside all candidate points
944 * generated using both edges in a parallel pair, and generated
945 * some additional candidate points half way between them. Also,
946 * of course, I'd have to cope with rounding error making such a
947 * point look worse than one of its endpoints. So I haven't done
948 * this for the moment, and will cross it if necessary when I come
949 * to it.)
950 *
951 * We don't actually iterate literally over _edges_, in the sense
952 * of grid_edge structures. Instead, we fill in edgedot1[] and
953 * edgedot2[] with a pair of dots adjacent in the face's list of
954 * vertices. This ensures that we get the edges in consistent
955 * orientation, which we could not do from the grid structure
956 * alone. (A moment's consideration of an order-3 vertex should
957 * make it clear that if a notional arrow was written on each
958 * edge, _at least one_ of the three faces bordering that vertex
959 * would have to have the two arrows tip-to-tip or tail-to-tail
960 * rather than tip-to-tail.)
961 */
962 nedges = ndots = 0;
963 bestdist = 0;
964 xbest = ybest = 0;
965
966 for (i = 0; i+2 < 2*f->order; i++) {
967 if (i < f->order) {
968 edgedot1[nedges] = f->dots[i];
969 edgedot2[nedges++] = f->dots[(i+1)%f->order];
970 } else
971 dots[ndots++] = f->dots[i - f->order];
972
973 for (j = i+1; j+1 < 2*f->order; j++) {
974 if (j < f->order) {
975 edgedot1[nedges] = f->dots[j];
976 edgedot2[nedges++] = f->dots[(j+1)%f->order];
977 } else
978 dots[ndots++] = f->dots[j - f->order];
979
980 for (k = j+1; k < 2*f->order; k++) {
981 double cx[2], cy[2]; /* candidate positions */
982 int cn = 0; /* number of candidates */
983
984 if (k < f->order) {
985 edgedot1[nedges] = f->dots[k];
986 edgedot2[nedges++] = f->dots[(k+1)%f->order];
987 } else
988 dots[ndots++] = f->dots[k - f->order];
989
990 /*
991 * Find a point, or pair of points, equidistant from
992 * all the specified edges and/or vertices.
993 */
994 if (nedges == 3) {
995 /*
996 * Three edges. This is a linear matrix equation:
997 * each row of the matrix represents the fact that
998 * the point (x,y) we seek is at distance r from
999 * that edge, and we solve three of those
1000 * simultaneously to obtain x,y,r. (We ignore r.)
1001 */
1002 double matrix[9], vector[3], vector2[3];
1003 int m;
1004
1005 for (m = 0; m < 3; m++) {
1006 int x1 = edgedot1[m]->x, x2 = edgedot2[m]->x;
1007 int y1 = edgedot1[m]->y, y2 = edgedot2[m]->y;
1008 int dx = x2-x1, dy = y2-y1;
1009
1010 /*
1011 * ((x,y) - (x1,y1)) . (dy,-dx) = r |(dx,dy)|
1012 *
1013 * => x dy - y dx - r |(dx,dy)| = (x1 dy - y1 dx)
1014 */
1015 matrix[3*m+0] = dy;
1016 matrix[3*m+1] = -dx;
1017 matrix[3*m+2] = -sqrt((double)dx*dx+(double)dy*dy);
1018 vector[m] = (double)x1*dy - (double)y1*dx;
1019 }
1020
1021 if (solve_3x3_matrix(matrix, vector, vector2)) {
1022 cx[cn] = vector2[0];
1023 cy[cn] = vector2[1];
1024 cn++;
1025 }
1026 } else if (nedges == 2) {
1027 /*
1028 * Two edges and a dot. This will end up in a
1029 * quadratic equation.
1030 *
1031 * First, look at the two edges. Having our point
1032 * be some distance r from both of them gives rise
1033 * to a pair of linear equations in x,y,r of the
1034 * form
1035 *
1036 * (x-x1) dy - (y-y1) dx = r sqrt(dx^2+dy^2)
1037 *
1038 * We eliminate r between those equations to give
1039 * us a single linear equation in x,y describing
1040 * the locus of points equidistant from both lines
1041 * - i.e. the angle bisector.
1042 *
1043 * We then choose one of x,y to be a parameter t,
1044 * and derive linear formulae for x,y,r in terms
1045 * of t. This enables us to write down the
1046 * circular equation (x-xd)^2+(y-yd)^2=r^2 as a
1047 * quadratic in t; solving that and substituting
1048 * in for x,y gives us two candidate points.
1049 */
1050 double eqs[2][4]; /* a,b,c,d : ax+by+cr=d */
1051 double eq[3]; /* a,b,c: ax+by=c */
1052 double xt[2], yt[2], rt[2]; /* a,b: {x,y,r}=at+b */
1053 double q[3]; /* a,b,c: at^2+bt+c=0 */
1054 double disc;
1055
1056 /* Find equations of the two input lines. */
1057 for (m = 0; m < 2; m++) {
1058 int x1 = edgedot1[m]->x, x2 = edgedot2[m]->x;
1059 int y1 = edgedot1[m]->y, y2 = edgedot2[m]->y;
1060 int dx = x2-x1, dy = y2-y1;
1061
1062 eqs[m][0] = dy;
1063 eqs[m][1] = -dx;
1064 eqs[m][2] = -sqrt(dx*dx+dy*dy);
1065 eqs[m][3] = x1*dy - y1*dx;
1066 }
1067
1068 /* Derive the angle bisector by eliminating r. */
1069 eq[0] = eqs[0][0]*eqs[1][2] - eqs[1][0]*eqs[0][2];
1070 eq[1] = eqs[0][1]*eqs[1][2] - eqs[1][1]*eqs[0][2];
1071 eq[2] = eqs[0][3]*eqs[1][2] - eqs[1][3]*eqs[0][2];
1072
1073 /* Parametrise x and y in terms of some t. */
1074 if (abs(eq[0]) < abs(eq[1])) {
1075 /* Parameter is x. */
1076 xt[0] = 1; xt[1] = 0;
1077 yt[0] = -eq[0]/eq[1]; yt[1] = eq[2]/eq[1];
1078 } else {
1079 /* Parameter is y. */
1080 yt[0] = 1; yt[1] = 0;
1081 xt[0] = -eq[1]/eq[0]; xt[1] = eq[2]/eq[0];
1082 }
1083
1084 /* Find a linear representation of r using eqs[0]. */
1085 rt[0] = -(eqs[0][0]*xt[0] + eqs[0][1]*yt[0])/eqs[0][2];
1086 rt[1] = (eqs[0][3] - eqs[0][0]*xt[1] -
1087 eqs[0][1]*yt[1])/eqs[0][2];
1088
1089 /* Construct the quadratic equation. */
1090 q[0] = -rt[0]*rt[0];
1091 q[1] = -2*rt[0]*rt[1];
1092 q[2] = -rt[1]*rt[1];
1093 q[0] += xt[0]*xt[0];
1094 q[1] += 2*xt[0]*(xt[1]-dots[0]->x);
1095 q[2] += (xt[1]-dots[0]->x)*(xt[1]-dots[0]->x);
1096 q[0] += yt[0]*yt[0];
1097 q[1] += 2*yt[0]*(yt[1]-dots[0]->y);
1098 q[2] += (yt[1]-dots[0]->y)*(yt[1]-dots[0]->y);
1099
1100 /* And solve it. */
1101 disc = q[1]*q[1] - 4*q[0]*q[2];
1102 if (disc >= 0) {
1103 double t;
1104
1105 disc = sqrt(disc);
1106
1107 t = (-q[1] + disc) / (2*q[0]);
1108 cx[cn] = xt[0]*t + xt[1];
1109 cy[cn] = yt[0]*t + yt[1];
1110 cn++;
1111
1112 t = (-q[1] - disc) / (2*q[0]);
1113 cx[cn] = xt[0]*t + xt[1];
1114 cy[cn] = yt[0]*t + yt[1];
1115 cn++;
1116 }
1117 } else if (nedges == 1) {
1118 /*
1119 * Two dots and an edge. This one's another
1120 * quadratic equation.
1121 *
1122 * The point we want must lie on the perpendicular
1123 * bisector of the two dots; that much is obvious.
1124 * So we can construct a parametrisation of that
1125 * bisecting line, giving linear formulae for x,y
1126 * in terms of t. We can also express the distance
1127 * from the edge as such a linear formula.
1128 *
1129 * Then we set that equal to the radius of the
1130 * circle passing through the two points, which is
1131 * a Pythagoras exercise; that gives rise to a
1132 * quadratic in t, which we solve.
1133 */
1134 double xt[2], yt[2], rt[2]; /* a,b: {x,y,r}=at+b */
1135 double q[3]; /* a,b,c: at^2+bt+c=0 */
1136 double disc;
1137 double halfsep;
1138
1139 /* Find parametric formulae for x,y. */
1140 {
1141 int x1 = dots[0]->x, x2 = dots[1]->x;
1142 int y1 = dots[0]->y, y2 = dots[1]->y;
1143 int dx = x2-x1, dy = y2-y1;
1144 double d = sqrt((double)dx*dx + (double)dy*dy);
1145
1146 xt[1] = (x1+x2)/2.0;
1147 yt[1] = (y1+y2)/2.0;
1148 /* It's convenient if we have t at standard scale. */
1149 xt[0] = -dy/d;
1150 yt[0] = dx/d;
1151
1152 /* Also note down half the separation between
1153 * the dots, for use in computing the circle radius. */
1154 halfsep = 0.5*d;
1155 }
1156
1157 /* Find a parametric formula for r. */
1158 {
1159 int x1 = edgedot1[0]->x, x2 = edgedot2[0]->x;
1160 int y1 = edgedot1[0]->y, y2 = edgedot2[0]->y;
1161 int dx = x2-x1, dy = y2-y1;
1162 double d = sqrt((double)dx*dx + (double)dy*dy);
1163 rt[0] = (xt[0]*dy - yt[0]*dx) / d;
1164 rt[1] = ((xt[1]-x1)*dy - (yt[1]-y1)*dx) / d;
1165 }
1166
1167 /* Construct the quadratic equation. */
1168 q[0] = rt[0]*rt[0];
1169 q[1] = 2*rt[0]*rt[1];
1170 q[2] = rt[1]*rt[1];
1171 q[0] -= 1;
1172 q[2] -= halfsep*halfsep;
1173
1174 /* And solve it. */
1175 disc = q[1]*q[1] - 4*q[0]*q[2];
1176 if (disc >= 0) {
1177 double t;
1178
1179 disc = sqrt(disc);
1180
1181 t = (-q[1] + disc) / (2*q[0]);
1182 cx[cn] = xt[0]*t + xt[1];
1183 cy[cn] = yt[0]*t + yt[1];
1184 cn++;
1185
1186 t = (-q[1] - disc) / (2*q[0]);
1187 cx[cn] = xt[0]*t + xt[1];
1188 cy[cn] = yt[0]*t + yt[1];
1189 cn++;
1190 }
1191 } else if (nedges == 0) {
1192 /*
1193 * Three dots. This is another linear matrix
1194 * equation, this time with each row of the matrix
1195 * representing the perpendicular bisector between
1196 * two of the points. Of course we only need two
1197 * such lines to find their intersection, so we
1198 * need only solve a 2x2 matrix equation.
1199 */
1200
1201 double matrix[4], vector[2], vector2[2];
1202 int m;
1203
1204 for (m = 0; m < 2; m++) {
1205 int x1 = dots[m]->x, x2 = dots[m+1]->x;
1206 int y1 = dots[m]->y, y2 = dots[m+1]->y;
1207 int dx = x2-x1, dy = y2-y1;
1208
1209 /*
1210 * ((x,y) - (x1,y1)) . (dx,dy) = 1/2 |(dx,dy)|^2
1211 *
1212 * => 2x dx + 2y dy = dx^2+dy^2 + (2 x1 dx + 2 y1 dy)
1213 */
1214 matrix[2*m+0] = 2*dx;
1215 matrix[2*m+1] = 2*dy;
1216 vector[m] = ((double)dx*dx + (double)dy*dy +
1217 2.0*x1*dx + 2.0*y1*dy);
1218 }
1219
1220 if (solve_2x2_matrix(matrix, vector, vector2)) {
1221 cx[cn] = vector2[0];
1222 cy[cn] = vector2[1];
1223 cn++;
1224 }
1225 }
1226
1227 /*
1228 * Now go through our candidate points and see if any
1229 * of them are better than what we've got so far.
1230 */
1231 for (m = 0; m < cn; m++) {
1232 double x = cx[m], y = cy[m];
1233
1234 /*
1235 * First, disqualify the point if it's not inside
1236 * the polygon, which we work out by counting the
1237 * edges to the right of the point. (For
1238 * tiebreaking purposes when edges start or end on
1239 * our y-coordinate or go right through it, we
1240 * consider our point to be offset by a small
1241 * _positive_ epsilon in both the x- and
1242 * y-direction.)
1243 */
1244 int e, in = 0;
1245 for (e = 0; e < f->order; e++) {
1246 int xs = f->edges[e]->dot1->x;
1247 int xe = f->edges[e]->dot2->x;
1248 int ys = f->edges[e]->dot1->y;
1249 int ye = f->edges[e]->dot2->y;
1250 if ((y >= ys && y < ye) || (y >= ye && y < ys)) {
1251 /*
1252 * The line goes past our y-position. Now we need
1253 * to know if its x-coordinate when it does so is
1254 * to our right.
1255 *
1256 * The x-coordinate in question is mathematically
1257 * (y - ys) * (xe - xs) / (ye - ys), and we want
1258 * to know whether (x - xs) >= that. Of course we
1259 * avoid the division, so we can work in integers;
1260 * to do this we must multiply both sides of the
1261 * inequality by ye - ys, which means we must
1262 * first check that's not negative.
1263 */
1264 int num = xe - xs, denom = ye - ys;
1265 if (denom < 0) {
1266 num = -num;
1267 denom = -denom;
1268 }
1269 if ((x - xs) * denom >= (y - ys) * num)
1270 in ^= 1;
1271 }
1272 }
1273
1274 if (in) {
1275 #ifdef HUGE_VAL
1276 double mindist = HUGE_VAL;
1277 #else
1278 #ifdef DBL_MAX
1279 double mindist = DBL_MAX;
1280 #else
1281 #error No way to get maximum floating-point number.
1282 #endif
1283 #endif
1284 int e, d;
1285
1286 /*
1287 * This point is inside the polygon, so now we check
1288 * its minimum distance to every edge and corner.
1289 * First the corners ...
1290 */
1291 for (d = 0; d < f->order; d++) {
1292 int xp = f->dots[d]->x;
1293 int yp = f->dots[d]->y;
1294 double dx = x - xp, dy = y - yp;
1295 double dist = dx*dx + dy*dy;
1296 if (mindist > dist)
1297 mindist = dist;
1298 }
1299
1300 /*
1301 * ... and now also check the perpendicular distance
1302 * to every edge, if the perpendicular lies between
1303 * the edge's endpoints.
1304 */
1305 for (e = 0; e < f->order; e++) {
1306 int xs = f->edges[e]->dot1->x;
1307 int xe = f->edges[e]->dot2->x;
1308 int ys = f->edges[e]->dot1->y;
1309 int ye = f->edges[e]->dot2->y;
1310
1311 /*
1312 * If s and e are our endpoints, and p our
1313 * candidate circle centre, the foot of a
1314 * perpendicular from p to the line se lies
1315 * between s and e if and only if (p-s).(e-s) lies
1316 * strictly between 0 and (e-s).(e-s).
1317 */
1318 int edx = xe - xs, edy = ye - ys;
1319 double pdx = x - xs, pdy = y - ys;
1320 double pde = pdx * edx + pdy * edy;
1321 long ede = (long)edx * edx + (long)edy * edy;
1322 if (0 < pde && pde < ede) {
1323 /*
1324 * Yes, the nearest point on this edge is
1325 * closer than either endpoint, so we must
1326 * take it into account by measuring the
1327 * perpendicular distance to the edge and
1328 * checking its square against mindist.
1329 */
1330
1331 double pdre = pdx * edy - pdy * edx;
1332 double sqlen = pdre * pdre / ede;
1333
1334 if (mindist > sqlen)
1335 mindist = sqlen;
1336 }
1337 }
1338
1339 /*
1340 * Right. Now we know the biggest circle around this
1341 * point, so we can check it against bestdist.
1342 */
1343 if (bestdist < mindist) {
1344 bestdist = mindist;
1345 xbest = x;
1346 ybest = y;
1347 }
1348 }
1349 }
1350
1351 if (k < f->order)
1352 nedges--;
1353 else
1354 ndots--;
1355 }
1356 if (j < f->order)
1357 nedges--;
1358 else
1359 ndots--;
1360 }
1361 if (i < f->order)
1362 nedges--;
1363 else
1364 ndots--;
1365 }
1366
1367 assert(bestdist > 0);
1368
1369 f->has_incentre = TRUE;
1370 f->ix = xbest + 0.5; /* round to nearest */
1371 f->iy = ybest + 0.5;
1372 }
1373
1374 /* Generate the dual to a grid
1375 * Returns a new dynamically-allocated grid whose dots are the
1376 * faces of the input, and whose faces are the dots of the input.
1377 * A few modifications are made: dots on input that have only two
1378 * edges are deleted, and the infinite exterior face is also removed
1379 * before conversion.
1380 */
1381 static grid *grid_dual(grid *g)
1382 {
1383 grid *new_g;
1384 int i, j, k;
1385 tree234* points;
1386
1387 new_g = grid_empty();
1388 new_g->tilesize = g->tilesize;
1389 new_g->faces = snewn(g->num_dots, grid_face);
1390 new_g->dots = snewn(g->num_faces, grid_dot);
1391 debug(("taking the dual of a grid with %d faces and %d dots\n",
1392 g->num_faces,g->num_dots));
1393
1394 points = newtree234(grid_point_cmp_fn);
1395
1396 for (i=0;i<g->num_faces;i++)
1397 {
1398 grid_find_incentre(&(g->faces[i]));
1399 }
1400 for (i=0;i<g->num_dots;i++)
1401 {
1402 int order;
1403 grid_dot *d;
1404
1405 d = &(g->dots[i]);
1406
1407 order = d->order;
1408 for (j=0;j<d->order;j++)
1409 {
1410 if (!d->faces[j]) order--;
1411 }
1412 if (order>2)
1413 {
1414 grid_face_add_new(new_g, order);
1415 for (j=0,k=0;j<d->order;j++)
1416 {
1417 grid_dot *new_d;
1418 if (d->faces[j])
1419 {
1420 new_d = grid_get_dot(new_g, points,
1421 d->faces[j]->ix, d->faces[j]->iy);
1422 grid_face_set_dot(new_g, new_d, k++);
1423 }
1424 }
1425 assert(k==order);
1426 }
1427 }
1428
1429 freetree234(points);
1430 assert(new_g->num_faces <= g->num_dots);
1431 assert(new_g->num_dots <= g->num_faces);
1432
1433 debug(("dual has %d faces and %d dots\n",
1434 new_g->num_faces,new_g->num_dots));
1435 grid_make_consistent(new_g);
1436 return new_g;
1437 }
1438 /* ------ Generate various types of grid ------ */
1439
1440 /* General method is to generate faces, by calculating their dot coordinates.
1441 * As new faces are added, we keep track of all the dots so we can tell when
1442 * a new face reuses an existing dot. For example, two squares touching at an
1443 * edge would generate six unique dots: four dots from the first face, then
1444 * two additional dots for the second face, because we detect the other two
1445 * dots have already been taken up. This list is stored in a tree234
1446 * called "points". No extra memory-allocation needed here - we store the
1447 * actual grid_dot* pointers, which all point into the g->dots list.
1448 * For this reason, we have to calculate coordinates in such a way as to
1449 * eliminate any rounding errors, so we can detect when a dot on one
1450 * face precisely lands on a dot of a different face. No floating-point
1451 * arithmetic here!
1452 */
1453
1454 #define SQUARE_TILESIZE 20
1455
1456 static void grid_size_square(int width, int height,
1457 int *tilesize, int *xextent, int *yextent)
1458 {
1459 int a = SQUARE_TILESIZE;
1460
1461 *tilesize = a;
1462 *xextent = width * a;
1463 *yextent = height * a;
1464 }
1465
1466 static grid *grid_new_square(int width, int height, char *desc)
1467 {
1468 int x, y;
1469 /* Side length */
1470 int a = SQUARE_TILESIZE;
1471
1472 /* Upper bounds - don't have to be exact */
1473 int max_faces = width * height;
1474 int max_dots = (width + 1) * (height + 1);
1475
1476 tree234 *points;
1477
1478 grid *g = grid_empty();
1479 g->tilesize = a;
1480 g->faces = snewn(max_faces, grid_face);
1481 g->dots = snewn(max_dots, grid_dot);
1482
1483 points = newtree234(grid_point_cmp_fn);
1484
1485 /* generate square faces */
1486 for (y = 0; y < height; y++) {
1487 for (x = 0; x < width; x++) {
1488 grid_dot *d;
1489 /* face position */
1490 int px = a * x;
1491 int py = a * y;
1492
1493 grid_face_add_new(g, 4);
1494 d = grid_get_dot(g, points, px, py);
1495 grid_face_set_dot(g, d, 0);
1496 d = grid_get_dot(g, points, px + a, py);
1497 grid_face_set_dot(g, d, 1);
1498 d = grid_get_dot(g, points, px + a, py + a);
1499 grid_face_set_dot(g, d, 2);
1500 d = grid_get_dot(g, points, px, py + a);
1501 grid_face_set_dot(g, d, 3);
1502 }
1503 }
1504
1505 freetree234(points);
1506 assert(g->num_faces <= max_faces);
1507 assert(g->num_dots <= max_dots);
1508
1509 grid_make_consistent(g);
1510 return g;
1511 }
1512
1513 #define HONEY_TILESIZE 45
1514 /* Vector for side of hexagon - ratio is close to sqrt(3) */
1515 #define HONEY_A 15
1516 #define HONEY_B 26
1517
1518 static void grid_size_honeycomb(int width, int height,
1519 int *tilesize, int *xextent, int *yextent)
1520 {
1521 int a = HONEY_A;
1522 int b = HONEY_B;
1523
1524 *tilesize = HONEY_TILESIZE;
1525 *xextent = (3 * a * (width-1)) + 4*a;
1526 *yextent = (2 * b * (height-1)) + 3*b;
1527 }
1528
1529 static grid *grid_new_honeycomb(int width, int height, char *desc)
1530 {
1531 int x, y;
1532 int a = HONEY_A;
1533 int b = HONEY_B;
1534
1535 /* Upper bounds - don't have to be exact */
1536 int max_faces = width * height;
1537 int max_dots = 2 * (width + 1) * (height + 1);
1538
1539 tree234 *points;
1540
1541 grid *g = grid_empty();
1542 g->tilesize = HONEY_TILESIZE;
1543 g->faces = snewn(max_faces, grid_face);
1544 g->dots = snewn(max_dots, grid_dot);
1545
1546 points = newtree234(grid_point_cmp_fn);
1547
1548 /* generate hexagonal faces */
1549 for (y = 0; y < height; y++) {
1550 for (x = 0; x < width; x++) {
1551 grid_dot *d;
1552 /* face centre */
1553 int cx = 3 * a * x;
1554 int cy = 2 * b * y;
1555 if (x % 2)
1556 cy += b;
1557 grid_face_add_new(g, 6);
1558
1559 d = grid_get_dot(g, points, cx - a, cy - b);
1560 grid_face_set_dot(g, d, 0);
1561 d = grid_get_dot(g, points, cx + a, cy - b);
1562 grid_face_set_dot(g, d, 1);
1563 d = grid_get_dot(g, points, cx + 2*a, cy);
1564 grid_face_set_dot(g, d, 2);
1565 d = grid_get_dot(g, points, cx + a, cy + b);
1566 grid_face_set_dot(g, d, 3);
1567 d = grid_get_dot(g, points, cx - a, cy + b);
1568 grid_face_set_dot(g, d, 4);
1569 d = grid_get_dot(g, points, cx - 2*a, cy);
1570 grid_face_set_dot(g, d, 5);
1571 }
1572 }
1573
1574 freetree234(points);
1575 assert(g->num_faces <= max_faces);
1576 assert(g->num_dots <= max_dots);
1577
1578 grid_make_consistent(g);
1579 return g;
1580 }
1581
1582 #define TRIANGLE_TILESIZE 18
1583 /* Vector for side of triangle - ratio is close to sqrt(3) */
1584 #define TRIANGLE_VEC_X 15
1585 #define TRIANGLE_VEC_Y 26
1586
1587 static void grid_size_triangular(int width, int height,
1588 int *tilesize, int *xextent, int *yextent)
1589 {
1590 int vec_x = TRIANGLE_VEC_X;
1591 int vec_y = TRIANGLE_VEC_Y;
1592
1593 *tilesize = TRIANGLE_TILESIZE;
1594 *xextent = width * 2 * vec_x + vec_x;
1595 *yextent = height * vec_y;
1596 }
1597
1598 /* Doesn't use the previous method of generation, it pre-dates it!
1599 * A triangular grid is just about simple enough to do by "brute force" */
1600 static grid *grid_new_triangular(int width, int height, char *desc)
1601 {
1602 int x,y;
1603
1604 /* Vector for side of triangle - ratio is close to sqrt(3) */
1605 int vec_x = TRIANGLE_VEC_X;
1606 int vec_y = TRIANGLE_VEC_Y;
1607
1608 int index;
1609
1610 /* convenient alias */
1611 int w = width + 1;
1612
1613 grid *g = grid_empty();
1614 g->tilesize = TRIANGLE_TILESIZE;
1615
1616 g->num_faces = width * height * 2;
1617 g->num_dots = (width + 1) * (height + 1);
1618 g->faces = snewn(g->num_faces, grid_face);
1619 g->dots = snewn(g->num_dots, grid_dot);
1620
1621 /* generate dots */
1622 index = 0;
1623 for (y = 0; y <= height; y++) {
1624 for (x = 0; x <= width; x++) {
1625 grid_dot *d = g->dots + index;
1626 /* odd rows are offset to the right */
1627 d->order = 0;
1628 d->edges = NULL;
1629 d->faces = NULL;
1630 d->x = x * 2 * vec_x + ((y % 2) ? vec_x : 0);
1631 d->y = y * vec_y;
1632 index++;
1633 }
1634 }
1635
1636 /* generate faces */
1637 index = 0;
1638 for (y = 0; y < height; y++) {
1639 for (x = 0; x < width; x++) {
1640 /* initialise two faces for this (x,y) */
1641 grid_face *f1 = g->faces + index;
1642 grid_face *f2 = f1 + 1;
1643 f1->edges = NULL;
1644 f1->order = 3;
1645 f1->dots = snewn(f1->order, grid_dot*);
1646 f1->has_incentre = FALSE;
1647 f2->edges = NULL;
1648 f2->order = 3;
1649 f2->dots = snewn(f2->order, grid_dot*);
1650 f2->has_incentre = FALSE;
1651
1652 /* face descriptions depend on whether the row-number is
1653 * odd or even */
1654 if (y % 2) {
1655 f1->dots[0] = g->dots + y * w + x;
1656 f1->dots[1] = g->dots + (y + 1) * w + x + 1;
1657 f1->dots[2] = g->dots + (y + 1) * w + x;
1658 f2->dots[0] = g->dots + y * w + x;
1659 f2->dots[1] = g->dots + y * w + x + 1;
1660 f2->dots[2] = g->dots + (y + 1) * w + x + 1;
1661 } else {
1662 f1->dots[0] = g->dots + y * w + x;
1663 f1->dots[1] = g->dots + y * w + x + 1;
1664 f1->dots[2] = g->dots + (y + 1) * w + x;
1665 f2->dots[0] = g->dots + y * w + x + 1;
1666 f2->dots[1] = g->dots + (y + 1) * w + x + 1;
1667 f2->dots[2] = g->dots + (y + 1) * w + x;
1668 }
1669 index += 2;
1670 }
1671 }
1672
1673 grid_make_consistent(g);
1674 return g;
1675 }
1676
1677 #define SNUBSQUARE_TILESIZE 18
1678 /* Vector for side of triangle - ratio is close to sqrt(3) */
1679 #define SNUBSQUARE_A 15
1680 #define SNUBSQUARE_B 26
1681
1682 static void grid_size_snubsquare(int width, int height,
1683 int *tilesize, int *xextent, int *yextent)
1684 {
1685 int a = SNUBSQUARE_A;
1686 int b = SNUBSQUARE_B;
1687
1688 *tilesize = SNUBSQUARE_TILESIZE;
1689 *xextent = (a+b) * (width-1) + a + b;
1690 *yextent = (a+b) * (height-1) + a + b;
1691 }
1692
1693 static grid *grid_new_snubsquare(int width, int height, char *desc)
1694 {
1695 int x, y;
1696 int a = SNUBSQUARE_A;
1697 int b = SNUBSQUARE_B;
1698
1699 /* Upper bounds - don't have to be exact */
1700 int max_faces = 3 * width * height;
1701 int max_dots = 2 * (width + 1) * (height + 1);
1702
1703 tree234 *points;
1704
1705 grid *g = grid_empty();
1706 g->tilesize = SNUBSQUARE_TILESIZE;
1707 g->faces = snewn(max_faces, grid_face);
1708 g->dots = snewn(max_dots, grid_dot);
1709
1710 points = newtree234(grid_point_cmp_fn);
1711
1712 for (y = 0; y < height; y++) {
1713 for (x = 0; x < width; x++) {
1714 grid_dot *d;
1715 /* face position */
1716 int px = (a + b) * x;
1717 int py = (a + b) * y;
1718
1719 /* generate square faces */
1720 grid_face_add_new(g, 4);
1721 if ((x + y) % 2) {
1722 d = grid_get_dot(g, points, px + a, py);
1723 grid_face_set_dot(g, d, 0);
1724 d = grid_get_dot(g, points, px + a + b, py + a);
1725 grid_face_set_dot(g, d, 1);
1726 d = grid_get_dot(g, points, px + b, py + a + b);
1727 grid_face_set_dot(g, d, 2);
1728 d = grid_get_dot(g, points, px, py + b);
1729 grid_face_set_dot(g, d, 3);
1730 } else {
1731 d = grid_get_dot(g, points, px + b, py);
1732 grid_face_set_dot(g, d, 0);
1733 d = grid_get_dot(g, points, px + a + b, py + b);
1734 grid_face_set_dot(g, d, 1);
1735 d = grid_get_dot(g, points, px + a, py + a + b);
1736 grid_face_set_dot(g, d, 2);
1737 d = grid_get_dot(g, points, px, py + a);
1738 grid_face_set_dot(g, d, 3);
1739 }
1740
1741 /* generate up/down triangles */
1742 if (x > 0) {
1743 grid_face_add_new(g, 3);
1744 if ((x + y) % 2) {
1745 d = grid_get_dot(g, points, px + a, py);
1746 grid_face_set_dot(g, d, 0);
1747 d = grid_get_dot(g, points, px, py + b);
1748 grid_face_set_dot(g, d, 1);
1749 d = grid_get_dot(g, points, px - a, py);
1750 grid_face_set_dot(g, d, 2);
1751 } else {
1752 d = grid_get_dot(g, points, px, py + a);
1753 grid_face_set_dot(g, d, 0);
1754 d = grid_get_dot(g, points, px + a, py + a + b);
1755 grid_face_set_dot(g, d, 1);
1756 d = grid_get_dot(g, points, px - a, py + a + b);
1757 grid_face_set_dot(g, d, 2);
1758 }
1759 }
1760
1761 /* generate left/right triangles */
1762 if (y > 0) {
1763 grid_face_add_new(g, 3);
1764 if ((x + y) % 2) {
1765 d = grid_get_dot(g, points, px + a, py);
1766 grid_face_set_dot(g, d, 0);
1767 d = grid_get_dot(g, points, px + a + b, py - a);
1768 grid_face_set_dot(g, d, 1);
1769 d = grid_get_dot(g, points, px + a + b, py + a);
1770 grid_face_set_dot(g, d, 2);
1771 } else {
1772 d = grid_get_dot(g, points, px, py - a);
1773 grid_face_set_dot(g, d, 0);
1774 d = grid_get_dot(g, points, px + b, py);
1775 grid_face_set_dot(g, d, 1);
1776 d = grid_get_dot(g, points, px, py + a);
1777 grid_face_set_dot(g, d, 2);
1778 }
1779 }
1780 }
1781 }
1782
1783 freetree234(points);
1784 assert(g->num_faces <= max_faces);
1785 assert(g->num_dots <= max_dots);
1786
1787 grid_make_consistent(g);
1788 return g;
1789 }
1790
1791 #define CAIRO_TILESIZE 40
1792 /* Vector for side of pentagon - ratio is close to (4+sqrt(7))/3 */
1793 #define CAIRO_A 14
1794 #define CAIRO_B 31
1795
1796 static void grid_size_cairo(int width, int height,
1797 int *tilesize, int *xextent, int *yextent)
1798 {
1799 int b = CAIRO_B; /* a unused in determining grid size. */
1800
1801 *tilesize = CAIRO_TILESIZE;
1802 *xextent = 2*b*(width-1) + 2*b;
1803 *yextent = 2*b*(height-1) + 2*b;
1804 }
1805
1806 static grid *grid_new_cairo(int width, int height, char *desc)
1807 {
1808 int x, y;
1809 int a = CAIRO_A;
1810 int b = CAIRO_B;
1811
1812 /* Upper bounds - don't have to be exact */
1813 int max_faces = 2 * width * height;
1814 int max_dots = 3 * (width + 1) * (height + 1);
1815
1816 tree234 *points;
1817
1818 grid *g = grid_empty();
1819 g->tilesize = CAIRO_TILESIZE;
1820 g->faces = snewn(max_faces, grid_face);
1821 g->dots = snewn(max_dots, grid_dot);
1822
1823 points = newtree234(grid_point_cmp_fn);
1824
1825 for (y = 0; y < height; y++) {
1826 for (x = 0; x < width; x++) {
1827 grid_dot *d;
1828 /* cell position */
1829 int px = 2 * b * x;
1830 int py = 2 * b * y;
1831
1832 /* horizontal pentagons */
1833 if (y > 0) {
1834 grid_face_add_new(g, 5);
1835 if ((x + y) % 2) {
1836 d = grid_get_dot(g, points, px + a, py - b);
1837 grid_face_set_dot(g, d, 0);
1838 d = grid_get_dot(g, points, px + 2*b - a, py - b);
1839 grid_face_set_dot(g, d, 1);
1840 d = grid_get_dot(g, points, px + 2*b, py);
1841 grid_face_set_dot(g, d, 2);
1842 d = grid_get_dot(g, points, px + b, py + a);
1843 grid_face_set_dot(g, d, 3);
1844 d = grid_get_dot(g, points, px, py);
1845 grid_face_set_dot(g, d, 4);
1846 } else {
1847 d = grid_get_dot(g, points, px, py);
1848 grid_face_set_dot(g, d, 0);
1849 d = grid_get_dot(g, points, px + b, py - a);
1850 grid_face_set_dot(g, d, 1);
1851 d = grid_get_dot(g, points, px + 2*b, py);
1852 grid_face_set_dot(g, d, 2);
1853 d = grid_get_dot(g, points, px + 2*b - a, py + b);
1854 grid_face_set_dot(g, d, 3);
1855 d = grid_get_dot(g, points, px + a, py + b);
1856 grid_face_set_dot(g, d, 4);
1857 }
1858 }
1859 /* vertical pentagons */
1860 if (x > 0) {
1861 grid_face_add_new(g, 5);
1862 if ((x + y) % 2) {
1863 d = grid_get_dot(g, points, px, py);
1864 grid_face_set_dot(g, d, 0);
1865 d = grid_get_dot(g, points, px + b, py + a);
1866 grid_face_set_dot(g, d, 1);
1867 d = grid_get_dot(g, points, px + b, py + 2*b - a);
1868 grid_face_set_dot(g, d, 2);
1869 d = grid_get_dot(g, points, px, py + 2*b);
1870 grid_face_set_dot(g, d, 3);
1871 d = grid_get_dot(g, points, px - a, py + b);
1872 grid_face_set_dot(g, d, 4);
1873 } else {
1874 d = grid_get_dot(g, points, px, py);
1875 grid_face_set_dot(g, d, 0);
1876 d = grid_get_dot(g, points, px + a, py + b);
1877 grid_face_set_dot(g, d, 1);
1878 d = grid_get_dot(g, points, px, py + 2*b);
1879 grid_face_set_dot(g, d, 2);
1880 d = grid_get_dot(g, points, px - b, py + 2*b - a);
1881 grid_face_set_dot(g, d, 3);
1882 d = grid_get_dot(g, points, px - b, py + a);
1883 grid_face_set_dot(g, d, 4);
1884 }
1885 }
1886 }
1887 }
1888
1889 freetree234(points);
1890 assert(g->num_faces <= max_faces);
1891 assert(g->num_dots <= max_dots);
1892
1893 grid_make_consistent(g);
1894 return g;
1895 }
1896
1897 #define GREATHEX_TILESIZE 18
1898 /* Vector for side of triangle - ratio is close to sqrt(3) */
1899 #define GREATHEX_A 15
1900 #define GREATHEX_B 26
1901
1902 static void grid_size_greathexagonal(int width, int height,
1903 int *tilesize, int *xextent, int *yextent)
1904 {
1905 int a = GREATHEX_A;
1906 int b = GREATHEX_B;
1907
1908 *tilesize = GREATHEX_TILESIZE;
1909 *xextent = (3*a + b) * (width-1) + 4*a;
1910 *yextent = (2*a + 2*b) * (height-1) + 3*b + a;
1911 }
1912
1913 static grid *grid_new_greathexagonal(int width, int height, char *desc)
1914 {
1915 int x, y;
1916 int a = GREATHEX_A;
1917 int b = GREATHEX_B;
1918
1919 /* Upper bounds - don't have to be exact */
1920 int max_faces = 6 * (width + 1) * (height + 1);
1921 int max_dots = 6 * width * height;
1922
1923 tree234 *points;
1924
1925 grid *g = grid_empty();
1926 g->tilesize = GREATHEX_TILESIZE;
1927 g->faces = snewn(max_faces, grid_face);
1928 g->dots = snewn(max_dots, grid_dot);
1929
1930 points = newtree234(grid_point_cmp_fn);
1931
1932 for (y = 0; y < height; y++) {
1933 for (x = 0; x < width; x++) {
1934 grid_dot *d;
1935 /* centre of hexagon */
1936 int px = (3*a + b) * x;
1937 int py = (2*a + 2*b) * y;
1938 if (x % 2)
1939 py += a + b;
1940
1941 /* hexagon */
1942 grid_face_add_new(g, 6);
1943 d = grid_get_dot(g, points, px - a, py - b);
1944 grid_face_set_dot(g, d, 0);
1945 d = grid_get_dot(g, points, px + a, py - b);
1946 grid_face_set_dot(g, d, 1);
1947 d = grid_get_dot(g, points, px + 2*a, py);
1948 grid_face_set_dot(g, d, 2);
1949 d = grid_get_dot(g, points, px + a, py + b);
1950 grid_face_set_dot(g, d, 3);
1951 d = grid_get_dot(g, points, px - a, py + b);
1952 grid_face_set_dot(g, d, 4);
1953 d = grid_get_dot(g, points, px - 2*a, py);
1954 grid_face_set_dot(g, d, 5);
1955
1956 /* square below hexagon */
1957 if (y < height - 1) {
1958 grid_face_add_new(g, 4);
1959 d = grid_get_dot(g, points, px - a, py + b);
1960 grid_face_set_dot(g, d, 0);
1961 d = grid_get_dot(g, points, px + a, py + b);
1962 grid_face_set_dot(g, d, 1);
1963 d = grid_get_dot(g, points, px + a, py + 2*a + b);
1964 grid_face_set_dot(g, d, 2);
1965 d = grid_get_dot(g, points, px - a, py + 2*a + b);
1966 grid_face_set_dot(g, d, 3);
1967 }
1968
1969 /* square below right */
1970 if ((x < width - 1) && (((x % 2) == 0) || (y < height - 1))) {
1971 grid_face_add_new(g, 4);
1972 d = grid_get_dot(g, points, px + 2*a, py);
1973 grid_face_set_dot(g, d, 0);
1974 d = grid_get_dot(g, points, px + 2*a + b, py + a);
1975 grid_face_set_dot(g, d, 1);
1976 d = grid_get_dot(g, points, px + a + b, py + a + b);
1977 grid_face_set_dot(g, d, 2);
1978 d = grid_get_dot(g, points, px + a, py + b);
1979 grid_face_set_dot(g, d, 3);
1980 }
1981
1982 /* square below left */
1983 if ((x > 0) && (((x % 2) == 0) || (y < height - 1))) {
1984 grid_face_add_new(g, 4);
1985 d = grid_get_dot(g, points, px - 2*a, py);
1986 grid_face_set_dot(g, d, 0);
1987 d = grid_get_dot(g, points, px - a, py + b);
1988 grid_face_set_dot(g, d, 1);
1989 d = grid_get_dot(g, points, px - a - b, py + a + b);
1990 grid_face_set_dot(g, d, 2);
1991 d = grid_get_dot(g, points, px - 2*a - b, py + a);
1992 grid_face_set_dot(g, d, 3);
1993 }
1994
1995 /* Triangle below right */
1996 if ((x < width - 1) && (y < height - 1)) {
1997 grid_face_add_new(g, 3);
1998 d = grid_get_dot(g, points, px + a, py + b);
1999 grid_face_set_dot(g, d, 0);
2000 d = grid_get_dot(g, points, px + a + b, py + a + b);
2001 grid_face_set_dot(g, d, 1);
2002 d = grid_get_dot(g, points, px + a, py + 2*a + b);
2003 grid_face_set_dot(g, d, 2);
2004 }
2005
2006 /* Triangle below left */
2007 if ((x > 0) && (y < height - 1)) {
2008 grid_face_add_new(g, 3);
2009 d = grid_get_dot(g, points, px - a, py + b);
2010 grid_face_set_dot(g, d, 0);
2011 d = grid_get_dot(g, points, px - a, py + 2*a + b);
2012 grid_face_set_dot(g, d, 1);
2013 d = grid_get_dot(g, points, px - a - b, py + a + b);
2014 grid_face_set_dot(g, d, 2);
2015 }
2016 }
2017 }
2018
2019 freetree234(points);
2020 assert(g->num_faces <= max_faces);
2021 assert(g->num_dots <= max_dots);
2022
2023 grid_make_consistent(g);
2024 return g;
2025 }
2026 #define OCTAGONAL_TILESIZE 40
2027 /* b/a approx sqrt(2) */
2028 #define OCTAGONAL_A 29
2029 #define OCTAGONAL_B 41
2030
2031 static void grid_size_octagonal(int width, int height,
2032 int *tilesize, int *xextent, int *yextent)
2033 {
2034 int a = OCTAGONAL_A;
2035 int b = OCTAGONAL_B;
2036
2037 *tilesize = OCTAGONAL_TILESIZE;
2038 *xextent = (2*a + b) * width;
2039 *yextent = (2*a + b) * height;
2040 }
2041
2042 static grid *grid_new_octagonal(int width, int height, char *desc)
2043 {
2044 int x, y;
2045 int a = OCTAGONAL_A;
2046 int b = OCTAGONAL_B;
2047
2048 /* Upper bounds - don't have to be exact */
2049 int max_faces = 2 * width * height;
2050 int max_dots = 4 * (width + 1) * (height + 1);
2051
2052 tree234 *points;
2053
2054 grid *g = grid_empty();
2055 g->tilesize = OCTAGONAL_TILESIZE;
2056 g->faces = snewn(max_faces, grid_face);
2057 g->dots = snewn(max_dots, grid_dot);
2058
2059 points = newtree234(grid_point_cmp_fn);
2060
2061 for (y = 0; y < height; y++) {
2062 for (x = 0; x < width; x++) {
2063 grid_dot *d;
2064 /* cell position */
2065 int px = (2*a + b) * x;
2066 int py = (2*a + b) * y;
2067 /* octagon */
2068 grid_face_add_new(g, 8);
2069 d = grid_get_dot(g, points, px + a, py);
2070 grid_face_set_dot(g, d, 0);
2071 d = grid_get_dot(g, points, px + a + b, py);
2072 grid_face_set_dot(g, d, 1);
2073 d = grid_get_dot(g, points, px + 2*a + b, py + a);
2074 grid_face_set_dot(g, d, 2);
2075 d = grid_get_dot(g, points, px + 2*a + b, py + a + b);
2076 grid_face_set_dot(g, d, 3);
2077 d = grid_get_dot(g, points, px + a + b, py + 2*a + b);
2078 grid_face_set_dot(g, d, 4);
2079 d = grid_get_dot(g, points, px + a, py + 2*a + b);
2080 grid_face_set_dot(g, d, 5);
2081 d = grid_get_dot(g, points, px, py + a + b);
2082 grid_face_set_dot(g, d, 6);
2083 d = grid_get_dot(g, points, px, py + a);
2084 grid_face_set_dot(g, d, 7);
2085
2086 /* diamond */
2087 if ((x > 0) && (y > 0)) {
2088 grid_face_add_new(g, 4);
2089 d = grid_get_dot(g, points, px, py - a);
2090 grid_face_set_dot(g, d, 0);
2091 d = grid_get_dot(g, points, px + a, py);
2092 grid_face_set_dot(g, d, 1);
2093 d = grid_get_dot(g, points, px, py + a);
2094 grid_face_set_dot(g, d, 2);
2095 d = grid_get_dot(g, points, px - a, py);
2096 grid_face_set_dot(g, d, 3);
2097 }
2098 }
2099 }
2100
2101 freetree234(points);
2102 assert(g->num_faces <= max_faces);
2103 assert(g->num_dots <= max_dots);
2104
2105 grid_make_consistent(g);
2106 return g;
2107 }
2108
2109 #define KITE_TILESIZE 40
2110 /* b/a approx sqrt(3) */
2111 #define KITE_A 15
2112 #define KITE_B 26
2113
2114 static void grid_size_kites(int width, int height,
2115 int *tilesize, int *xextent, int *yextent)
2116 {
2117 int a = KITE_A;
2118 int b = KITE_B;
2119
2120 *tilesize = KITE_TILESIZE;
2121 *xextent = 4*b * width + 2*b;
2122 *yextent = 6*a * (height-1) + 8*a;
2123 }
2124
2125 static grid *grid_new_kites(int width, int height, char *desc)
2126 {
2127 int x, y;
2128 int a = KITE_A;
2129 int b = KITE_B;
2130
2131 /* Upper bounds - don't have to be exact */
2132 int max_faces = 6 * width * height;
2133 int max_dots = 6 * (width + 1) * (height + 1);
2134
2135 tree234 *points;
2136
2137 grid *g = grid_empty();
2138 g->tilesize = KITE_TILESIZE;
2139 g->faces = snewn(max_faces, grid_face);
2140 g->dots = snewn(max_dots, grid_dot);
2141
2142 points = newtree234(grid_point_cmp_fn);
2143
2144 for (y = 0; y < height; y++) {
2145 for (x = 0; x < width; x++) {
2146 grid_dot *d;
2147 /* position of order-6 dot */
2148 int px = 4*b * x;
2149 int py = 6*a * y;
2150 if (y % 2)
2151 px += 2*b;
2152
2153 /* kite pointing up-left */
2154 grid_face_add_new(g, 4);
2155 d = grid_get_dot(g, points, px, py);
2156 grid_face_set_dot(g, d, 0);
2157 d = grid_get_dot(g, points, px + 2*b, py);
2158 grid_face_set_dot(g, d, 1);
2159 d = grid_get_dot(g, points, px + 2*b, py + 2*a);
2160 grid_face_set_dot(g, d, 2);
2161 d = grid_get_dot(g, points, px + b, py + 3*a);
2162 grid_face_set_dot(g, d, 3);
2163
2164 /* kite pointing up */
2165 grid_face_add_new(g, 4);
2166 d = grid_get_dot(g, points, px, py);
2167 grid_face_set_dot(g, d, 0);
2168 d = grid_get_dot(g, points, px + b, py + 3*a);
2169 grid_face_set_dot(g, d, 1);
2170 d = grid_get_dot(g, points, px, py + 4*a);
2171 grid_face_set_dot(g, d, 2);
2172 d = grid_get_dot(g, points, px - b, py + 3*a);
2173 grid_face_set_dot(g, d, 3);
2174
2175 /* kite pointing up-right */
2176 grid_face_add_new(g, 4);
2177 d = grid_get_dot(g, points, px, py);
2178 grid_face_set_dot(g, d, 0);
2179 d = grid_get_dot(g, points, px - b, py + 3*a);
2180 grid_face_set_dot(g, d, 1);
2181 d = grid_get_dot(g, points, px - 2*b, py + 2*a);
2182 grid_face_set_dot(g, d, 2);
2183 d = grid_get_dot(g, points, px - 2*b, py);
2184 grid_face_set_dot(g, d, 3);
2185
2186 /* kite pointing down-right */
2187 grid_face_add_new(g, 4);
2188 d = grid_get_dot(g, points, px, py);
2189 grid_face_set_dot(g, d, 0);
2190 d = grid_get_dot(g, points, px - 2*b, py);
2191 grid_face_set_dot(g, d, 1);
2192 d = grid_get_dot(g, points, px - 2*b, py - 2*a);
2193 grid_face_set_dot(g, d, 2);
2194 d = grid_get_dot(g, points, px - b, py - 3*a);
2195 grid_face_set_dot(g, d, 3);
2196
2197 /* kite pointing down */
2198 grid_face_add_new(g, 4);
2199 d = grid_get_dot(g, points, px, py);
2200 grid_face_set_dot(g, d, 0);
2201 d = grid_get_dot(g, points, px - b, py - 3*a);
2202 grid_face_set_dot(g, d, 1);
2203 d = grid_get_dot(g, points, px, py - 4*a);
2204 grid_face_set_dot(g, d, 2);
2205 d = grid_get_dot(g, points, px + b, py - 3*a);
2206 grid_face_set_dot(g, d, 3);
2207
2208 /* kite pointing down-left */
2209 grid_face_add_new(g, 4);
2210 d = grid_get_dot(g, points, px, py);
2211 grid_face_set_dot(g, d, 0);
2212 d = grid_get_dot(g, points, px + b, py - 3*a);
2213 grid_face_set_dot(g, d, 1);
2214 d = grid_get_dot(g, points, px + 2*b, py - 2*a);
2215 grid_face_set_dot(g, d, 2);
2216 d = grid_get_dot(g, points, px + 2*b, py);
2217 grid_face_set_dot(g, d, 3);
2218 }
2219 }
2220
2221 freetree234(points);
2222 assert(g->num_faces <= max_faces);
2223 assert(g->num_dots <= max_dots);
2224
2225 grid_make_consistent(g);
2226 return g;
2227 }
2228
2229 #define FLORET_TILESIZE 150
2230 /* -py/px is close to tan(30 - atan(sqrt(3)/9))
2231 * using py=26 makes everything lean to the left, rather than right
2232 */
2233 #define FLORET_PX 75
2234 #define FLORET_PY -26
2235
2236 static void grid_size_floret(int width, int height,
2237 int *tilesize, int *xextent, int *yextent)
2238 {
2239 int px = FLORET_PX, py = FLORET_PY; /* |( 75, -26)| = 79.43 */
2240 int qx = 4*px/5, qy = -py*2; /* |( 60, 52)| = 79.40 */
2241 int ry = qy-py;
2242 /* rx unused in determining grid size. */
2243
2244 *tilesize = FLORET_TILESIZE;
2245 *xextent = (6*px+3*qx)/2 * (width-1) + 4*qx + 2*px;
2246 *yextent = (5*qy-4*py) * (height-1) + 4*qy + 2*ry;
2247 }
2248
2249 static grid *grid_new_floret(int width, int height, char *desc)
2250 {
2251 int x, y;
2252 /* Vectors for sides; weird numbers needed to keep puzzle aligned with window
2253 * -py/px is close to tan(30 - atan(sqrt(3)/9))
2254 * using py=26 makes everything lean to the left, rather than right
2255 */
2256 int px = FLORET_PX, py = FLORET_PY; /* |( 75, -26)| = 79.43 */
2257 int qx = 4*px/5, qy = -py*2; /* |( 60, 52)| = 79.40 */
2258 int rx = qx-px, ry = qy-py; /* |(-15, 78)| = 79.38 */
2259
2260 /* Upper bounds - don't have to be exact */
2261 int max_faces = 6 * width * height;
2262 int max_dots = 9 * (width + 1) * (height + 1);
2263
2264 tree234 *points;
2265
2266 grid *g = grid_empty();
2267 g->tilesize = FLORET_TILESIZE;
2268 g->faces = snewn(max_faces, grid_face);
2269 g->dots = snewn(max_dots, grid_dot);
2270
2271 points = newtree234(grid_point_cmp_fn);
2272
2273 /* generate pentagonal faces */
2274 for (y = 0; y < height; y++) {
2275 for (x = 0; x < width; x++) {
2276 grid_dot *d;
2277 /* face centre */
2278 int cx = (6*px+3*qx)/2 * x;
2279 int cy = (4*py-5*qy) * y;
2280 if (x % 2)
2281 cy -= (4*py-5*qy)/2;
2282 else if (y && y == height-1)
2283 continue; /* make better looking grids? try 3x3 for instance */
2284
2285 grid_face_add_new(g, 5);
2286 d = grid_get_dot(g, points, cx , cy ); grid_face_set_dot(g, d, 0);
2287 d = grid_get_dot(g, points, cx+2*rx , cy+2*ry ); grid_face_set_dot(g, d, 1);
2288 d = grid_get_dot(g, points, cx+2*rx+qx, cy+2*ry+qy); grid_face_set_dot(g, d, 2);
2289 d = grid_get_dot(g, points, cx+2*qx+rx, cy+2*qy+ry); grid_face_set_dot(g, d, 3);
2290 d = grid_get_dot(g, points, cx+2*qx , cy+2*qy ); grid_face_set_dot(g, d, 4);
2291
2292 grid_face_add_new(g, 5);
2293 d = grid_get_dot(g, points, cx , cy ); grid_face_set_dot(g, d, 0);
2294 d = grid_get_dot(g, points, cx+2*qx , cy+2*qy ); grid_face_set_dot(g, d, 1);
2295 d = grid_get_dot(g, points, cx+2*qx+px, cy+2*qy+py); grid_face_set_dot(g, d, 2);
2296 d = grid_get_dot(g, points, cx+2*px+qx, cy+2*py+qy); grid_face_set_dot(g, d, 3);
2297 d = grid_get_dot(g, points, cx+2*px , cy+2*py ); grid_face_set_dot(g, d, 4);
2298
2299 grid_face_add_new(g, 5);
2300 d = grid_get_dot(g, points, cx , cy ); grid_face_set_dot(g, d, 0);
2301 d = grid_get_dot(g, points, cx+2*px , cy+2*py ); grid_face_set_dot(g, d, 1);
2302 d = grid_get_dot(g, points, cx+2*px-rx, cy+2*py-ry); grid_face_set_dot(g, d, 2);
2303 d = grid_get_dot(g, points, cx-2*rx+px, cy-2*ry+py); grid_face_set_dot(g, d, 3);
2304 d = grid_get_dot(g, points, cx-2*rx , cy-2*ry ); grid_face_set_dot(g, d, 4);
2305
2306 grid_face_add_new(g, 5);
2307 d = grid_get_dot(g, points, cx , cy ); grid_face_set_dot(g, d, 0);
2308 d = grid_get_dot(g, points, cx-2*rx , cy-2*ry ); grid_face_set_dot(g, d, 1);
2309 d = grid_get_dot(g, points, cx-2*rx-qx, cy-2*ry-qy); grid_face_set_dot(g, d, 2);
2310 d = grid_get_dot(g, points, cx-2*qx-rx, cy-2*qy-ry); grid_face_set_dot(g, d, 3);
2311 d = grid_get_dot(g, points, cx-2*qx , cy-2*qy ); grid_face_set_dot(g, d, 4);
2312
2313 grid_face_add_new(g, 5);
2314 d = grid_get_dot(g, points, cx , cy ); grid_face_set_dot(g, d, 0);
2315 d = grid_get_dot(g, points, cx-2*qx , cy-2*qy ); grid_face_set_dot(g, d, 1);
2316 d = grid_get_dot(g, points, cx-2*qx-px, cy-2*qy-py); grid_face_set_dot(g, d, 2);
2317 d = grid_get_dot(g, points, cx-2*px-qx, cy-2*py-qy); grid_face_set_dot(g, d, 3);
2318 d = grid_get_dot(g, points, cx-2*px , cy-2*py ); grid_face_set_dot(g, d, 4);
2319
2320 grid_face_add_new(g, 5);
2321 d = grid_get_dot(g, points, cx , cy ); grid_face_set_dot(g, d, 0);
2322 d = grid_get_dot(g, points, cx-2*px , cy-2*py ); grid_face_set_dot(g, d, 1);
2323 d = grid_get_dot(g, points, cx-2*px+rx, cy-2*py+ry); grid_face_set_dot(g, d, 2);
2324 d = grid_get_dot(g, points, cx+2*rx-px, cy+2*ry-py); grid_face_set_dot(g, d, 3);
2325 d = grid_get_dot(g, points, cx+2*rx , cy+2*ry ); grid_face_set_dot(g, d, 4);
2326 }
2327 }
2328
2329 freetree234(points);
2330 assert(g->num_faces <= max_faces);
2331 assert(g->num_dots <= max_dots);
2332
2333 grid_make_consistent(g);
2334 return g;
2335 }
2336
2337 /* DODEC_* are used for dodecagonal and great-dodecagonal grids. */
2338 #define DODEC_TILESIZE 26
2339 /* Vector for side of triangle - ratio is close to sqrt(3) */
2340 #define DODEC_A 15
2341 #define DODEC_B 26
2342
2343 static void grid_size_dodecagonal(int width, int height,
2344 int *tilesize, int *xextent, int *yextent)
2345 {
2346 int a = DODEC_A;
2347 int b = DODEC_B;
2348
2349 *tilesize = DODEC_TILESIZE;
2350 *xextent = (4*a + 2*b) * (width-1) + 3*(2*a + b);
2351 *yextent = (3*a + 2*b) * (height-1) + 2*(2*a + b);
2352 }
2353
2354 static grid *grid_new_dodecagonal(int width, int height, char *desc)
2355 {
2356 int x, y;
2357 int a = DODEC_A;
2358 int b = DODEC_B;
2359
2360 /* Upper bounds - don't have to be exact */
2361 int max_faces = 3 * width * height;
2362 int max_dots = 14 * width * height;
2363
2364 tree234 *points;
2365
2366 grid *g = grid_empty();
2367 g->tilesize = DODEC_TILESIZE;
2368 g->faces = snewn(max_faces, grid_face);
2369 g->dots = snewn(max_dots, grid_dot);
2370
2371 points = newtree234(grid_point_cmp_fn);
2372
2373 for (y = 0; y < height; y++) {
2374 for (x = 0; x < width; x++) {
2375 grid_dot *d;
2376 /* centre of dodecagon */
2377 int px = (4*a + 2*b) * x;
2378 int py = (3*a + 2*b) * y;
2379 if (y % 2)
2380 px += 2*a + b;
2381
2382 /* dodecagon */
2383 grid_face_add_new(g, 12);
2384 d = grid_get_dot(g, points, px + ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 0);
2385 d = grid_get_dot(g, points, px + ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 1);
2386 d = grid_get_dot(g, points, px + (2*a + b), py - ( a )); grid_face_set_dot(g, d, 2);
2387 d = grid_get_dot(g, points, px + (2*a + b), py + ( a )); grid_face_set_dot(g, d, 3);
2388 d = grid_get_dot(g, points, px + ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 4);
2389 d = grid_get_dot(g, points, px + ( a ), py + (2*a + b)); grid_face_set_dot(g, d, 5);
2390 d = grid_get_dot(g, points, px - ( a ), py + (2*a + b)); grid_face_set_dot(g, d, 6);
2391 d = grid_get_dot(g, points, px - ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 7);
2392 d = grid_get_dot(g, points, px - (2*a + b), py + ( a )); grid_face_set_dot(g, d, 8);
2393 d = grid_get_dot(g, points, px - (2*a + b), py - ( a )); grid_face_set_dot(g, d, 9);
2394 d = grid_get_dot(g, points, px - ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 10);
2395 d = grid_get_dot(g, points, px - ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 11);
2396
2397 /* triangle below dodecagon */
2398 if ((y < height - 1 && (x < width - 1 || !(y % 2)) && (x > 0 || (y % 2)))) {
2399 grid_face_add_new(g, 3);
2400 d = grid_get_dot(g, points, px + a, py + (2*a + b)); grid_face_set_dot(g, d, 0);
2401 d = grid_get_dot(g, points, px , py + (2*a + 2*b)); grid_face_set_dot(g, d, 1);
2402 d = grid_get_dot(g, points, px - a, py + (2*a + b)); grid_face_set_dot(g, d, 2);
2403 }
2404
2405 /* triangle above dodecagon */
2406 if ((y && (x < width - 1 || !(y % 2)) && (x > 0 || (y % 2)))) {
2407 grid_face_add_new(g, 3);
2408 d = grid_get_dot(g, points, px - a, py - (2*a + b)); grid_face_set_dot(g, d, 0);
2409 d = grid_get_dot(g, points, px , py - (2*a + 2*b)); grid_face_set_dot(g, d, 1);
2410 d = grid_get_dot(g, points, px + a, py - (2*a + b)); grid_face_set_dot(g, d, 2);
2411 }
2412 }
2413 }
2414
2415 freetree234(points);
2416 assert(g->num_faces <= max_faces);
2417 assert(g->num_dots <= max_dots);
2418
2419 grid_make_consistent(g);
2420 return g;
2421 }
2422
2423 static void grid_size_greatdodecagonal(int width, int height,
2424 int *tilesize, int *xextent, int *yextent)
2425 {
2426 int a = DODEC_A;
2427 int b = DODEC_B;
2428
2429 *tilesize = DODEC_TILESIZE;
2430 *xextent = (6*a + 2*b) * (width-1) + 2*(2*a + b) + 3*a + b;
2431 *yextent = (3*a + 3*b) * (height-1) + 2*(2*a + b);
2432 }
2433
2434 static grid *grid_new_greatdodecagonal(int width, int height, char *desc)
2435 {
2436 int x, y;
2437 /* Vector for side of triangle - ratio is close to sqrt(3) */
2438 int a = DODEC_A;
2439 int b = DODEC_B;
2440
2441 /* Upper bounds - don't have to be exact */
2442 int max_faces = 30 * width * height;
2443 int max_dots = 200 * width * height;
2444
2445 tree234 *points;
2446
2447 grid *g = grid_empty();
2448 g->tilesize = DODEC_TILESIZE;
2449 g->faces = snewn(max_faces, grid_face);
2450 g->dots = snewn(max_dots, grid_dot);
2451
2452 points = newtree234(grid_point_cmp_fn);
2453
2454 for (y = 0; y < height; y++) {
2455 for (x = 0; x < width; x++) {
2456 grid_dot *d;
2457 /* centre of dodecagon */
2458 int px = (6*a + 2*b) * x;
2459 int py = (3*a + 3*b) * y;
2460 if (y % 2)
2461 px += 3*a + b;
2462
2463 /* dodecagon */
2464 grid_face_add_new(g, 12);
2465 d = grid_get_dot(g, points, px + ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 0);
2466 d = grid_get_dot(g, points, px + ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 1);
2467 d = grid_get_dot(g, points, px + (2*a + b), py - ( a )); grid_face_set_dot(g, d, 2);
2468 d = grid_get_dot(g, points, px + (2*a + b), py + ( a )); grid_face_set_dot(g, d, 3);
2469 d = grid_get_dot(g, points, px + ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 4);
2470 d = grid_get_dot(g, points, px + ( a ), py + (2*a + b)); grid_face_set_dot(g, d, 5);
2471 d = grid_get_dot(g, points, px - ( a ), py + (2*a + b)); grid_face_set_dot(g, d, 6);
2472 d = grid_get_dot(g, points, px - ( a + b), py + ( a + b)); grid_face_set_dot(g, d, 7);
2473 d = grid_get_dot(g, points, px - (2*a + b), py + ( a )); grid_face_set_dot(g, d, 8);
2474 d = grid_get_dot(g, points, px - (2*a + b), py - ( a )); grid_face_set_dot(g, d, 9);
2475 d = grid_get_dot(g, points, px - ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 10);
2476 d = grid_get_dot(g, points, px - ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 11);
2477
2478 /* hexagon below dodecagon */
2479 if (y < height - 1 && (x < width - 1 || !(y % 2)) && (x > 0 || (y % 2))) {
2480 grid_face_add_new(g, 6);
2481 d = grid_get_dot(g, points, px + a, py + (2*a + b)); grid_face_set_dot(g, d, 0);
2482 d = grid_get_dot(g, points, px + 2*a, py + (2*a + 2*b)); grid_face_set_dot(g, d, 1);
2483 d = grid_get_dot(g, points, px + a, py + (2*a + 3*b)); grid_face_set_dot(g, d, 2);
2484 d = grid_get_dot(g, points, px - a, py + (2*a + 3*b)); grid_face_set_dot(g, d, 3);
2485 d = grid_get_dot(g, points, px - 2*a, py + (2*a + 2*b)); grid_face_set_dot(g, d, 4);
2486 d = grid_get_dot(g, points, px - a, py + (2*a + b)); grid_face_set_dot(g, d, 5);
2487 }
2488
2489 /* hexagon above dodecagon */
2490 if (y && (x < width - 1 || !(y % 2)) && (x > 0 || (y % 2))) {
2491 grid_face_add_new(g, 6);
2492 d = grid_get_dot(g, points, px - a, py - (2*a + b)); grid_face_set_dot(g, d, 0);
2493 d = grid_get_dot(g, points, px - 2*a, py - (2*a + 2*b)); grid_face_set_dot(g, d, 1);
2494 d = grid_get_dot(g, points, px - a, py - (2*a + 3*b)); grid_face_set_dot(g, d, 2);
2495 d = grid_get_dot(g, points, px + a, py - (2*a + 3*b)); grid_face_set_dot(g, d, 3);
2496 d = grid_get_dot(g, points, px + 2*a, py - (2*a + 2*b)); grid_face_set_dot(g, d, 4);
2497 d = grid_get_dot(g, points, px + a, py - (2*a + b)); grid_face_set_dot(g, d, 5);
2498 }
2499
2500 /* square on right of dodecagon */
2501 if (x < width - 1) {
2502 grid_face_add_new(g, 4);
2503 d = grid_get_dot(g, points, px + 2*a + b, py - a); grid_face_set_dot(g, d, 0);
2504 d = grid_get_dot(g, points, px + 4*a + b, py - a); grid_face_set_dot(g, d, 1);
2505 d = grid_get_dot(g, points, px + 4*a + b, py + a); grid_face_set_dot(g, d, 2);
2506 d = grid_get_dot(g, points, px + 2*a + b, py + a); grid_face_set_dot(g, d, 3);
2507 }
2508
2509 /* square on top right of dodecagon */
2510 if (y && (x < width - 1 || !(y % 2))) {
2511 grid_face_add_new(g, 4);
2512 d = grid_get_dot(g, points, px + ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 0);
2513 d = grid_get_dot(g, points, px + (2*a ), py - (2*a + 2*b)); grid_face_set_dot(g, d, 1);
2514 d = grid_get_dot(g, points, px + (2*a + b), py - ( a + 2*b)); grid_face_set_dot(g, d, 2);
2515 d = grid_get_dot(g, points, px + ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 3);
2516 }
2517
2518 /* square on top left of dodecagon */
2519 if (y && (x || (y % 2))) {
2520 grid_face_add_new(g, 4);
2521 d = grid_get_dot(g, points, px - ( a + b), py - ( a + b)); grid_face_set_dot(g, d, 0);
2522 d = grid_get_dot(g, points, px - (2*a + b), py - ( a + 2*b)); grid_face_set_dot(g, d, 1);
2523 d = grid_get_dot(g, points, px - (2*a ), py - (2*a + 2*b)); grid_face_set_dot(g, d, 2);
2524 d = grid_get_dot(g, points, px - ( a ), py - (2*a + b)); grid_face_set_dot(g, d, 3);
2525 }
2526 }
2527 }
2528
2529 freetree234(points);
2530 assert(g->num_faces <= max_faces);
2531 assert(g->num_dots <= max_dots);
2532
2533 grid_make_consistent(g);
2534 return g;
2535 }
2536
2537 typedef struct setface_ctx
2538 {
2539 int xmin, xmax, ymin, ymax;
2540
2541 grid *g;
2542 tree234 *points;
2543 } setface_ctx;
2544
2545 static double round_int_nearest_away(double r)
2546 {
2547 return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
2548 }
2549
2550 static int set_faces(penrose_state *state, vector *vs, int n, int depth)
2551 {
2552 setface_ctx *sf_ctx = (setface_ctx *)state->ctx;
2553 int i;
2554 int xs[4], ys[4];
2555
2556 if (depth < state->max_depth) return 0;
2557 #ifdef DEBUG_PENROSE
2558 if (n != 4) return 0; /* triangles are sent as debugging. */
2559 #endif
2560
2561 for (i = 0; i < n; i++) {
2562 double tx = v_x(vs, i), ty = v_y(vs, i);
2563
2564 xs[i] = (int)round_int_nearest_away(tx);
2565 ys[i] = (int)round_int_nearest_away(ty);
2566
2567 if (xs[i] < sf_ctx->xmin || xs[i] > sf_ctx->xmax) return 0;
2568 if (ys[i] < sf_ctx->ymin || ys[i] > sf_ctx->ymax) return 0;
2569 }
2570
2571 grid_face_add_new(sf_ctx->g, n);
2572 debug(("penrose: new face l=%f gen=%d...",
2573 penrose_side_length(state->start_size, depth), depth));
2574 for (i = 0; i < n; i++) {
2575 grid_dot *d = grid_get_dot(sf_ctx->g, sf_ctx->points,
2576 xs[i], ys[i]);
2577 grid_face_set_dot(sf_ctx->g, d, i);
2578 debug((" ... dot 0x%x (%d,%d) (was %2.2f,%2.2f)",
2579 d, d->x, d->y, v_x(vs, i), v_y(vs, i)));
2580 }
2581
2582 return 0;
2583 }
2584
2585 #define PENROSE_TILESIZE 100
2586
2587 static void grid_size_penrose(int width, int height,
2588 int *tilesize, int *xextent, int *yextent)
2589 {
2590 int l = PENROSE_TILESIZE;
2591
2592 *tilesize = l;
2593 *xextent = l * width;
2594 *yextent = l * height;
2595 }
2596
2597 static char *grid_new_desc_penrose(grid_type type, int width, int height, random_state *rs)
2598 {
2599 int tilesize = PENROSE_TILESIZE, startsz, depth, xoff, yoff, aoff;
2600 double outer_radius;
2601 int inner_radius;
2602 char gd[255];
2603 int which = (type == GRID_PENROSE_P2 ? PENROSE_P2 : PENROSE_P3);
2604
2605 /* We want to produce a random bit of penrose tiling, so we calculate
2606 * a random offset (within the patch that penrose.c calculates for us)
2607 * and an angle (multiple of 36) to rotate the patch. */
2608
2609 penrose_calculate_size(which, tilesize, width, height,
2610 &outer_radius, &startsz, &depth);
2611
2612 /* Calculate radius of (circumcircle of) patch, subtract from
2613 * radius calculated. */
2614 inner_radius = (int)(outer_radius - sqrt(width*width + height*height));
2615
2616 /* Pick a random offset (the easy way: choose within outer square,
2617 * discarding while it's outside the circle) */
2618 do {
2619 xoff = random_upto(rs, 2*inner_radius) - inner_radius;
2620 yoff = random_upto(rs, 2*inner_radius) - inner_radius;
2621 } while (sqrt(xoff*xoff+yoff*yoff) > inner_radius);
2622
2623 aoff = random_upto(rs, 360/36) * 36;
2624
2625 debug(("grid_desc: ts %d, %dx%d patch, orad %2.2f irad %d",
2626 tilesize, width, height, outer_radius, inner_radius));
2627 debug((" -> xoff %d yoff %d aoff %d", xoff, yoff, aoff));
2628
2629 sprintf(gd, "G%d,%d,%d", xoff, yoff, aoff);
2630
2631 return dupstr(gd);
2632 }
2633
2634 static char *grid_validate_desc_penrose(grid_type type, int width, int height, char *desc)
2635 {
2636 int tilesize = PENROSE_TILESIZE, startsz, depth, xoff, yoff, aoff, inner_radius;
2637 double outer_radius;
2638 int which = (type == GRID_PENROSE_P2 ? PENROSE_P2 : PENROSE_P3);
2639
2640 if (!desc)
2641 return "Missing grid description string.";
2642
2643 penrose_calculate_size(which, tilesize, width, height,
2644 &outer_radius, &startsz, &depth);
2645 inner_radius = (int)(outer_radius - sqrt(width*width + height*height));
2646
2647 if (sscanf(desc, "G%d,%d,%d", &xoff, &yoff, &aoff) != 3)
2648 return "Invalid format grid description string.";
2649
2650 if (sqrt(xoff*xoff + yoff*yoff) > inner_radius)
2651 return "Patch offset out of bounds.";
2652 if ((aoff % 36) != 0 || aoff < 0 || aoff >= 360)
2653 return "Angle offset out of bounds.";
2654
2655 return NULL;
2656 }
2657
2658 /*
2659 * We're asked for a grid of a particular size, and we generate enough
2660 * of the tiling so we can be sure to have enough random grid from which
2661 * to pick.
2662 */
2663
2664 static grid *grid_new_penrose(int width, int height, int which, char *desc)
2665 {
2666 int max_faces, max_dots, tilesize = PENROSE_TILESIZE;
2667 int xsz, ysz, xoff, yoff, aoff;
2668 double rradius;
2669
2670 tree234 *points;
2671 grid *g;
2672
2673 penrose_state ps;
2674 setface_ctx sf_ctx;
2675
2676 penrose_calculate_size(which, tilesize, width, height,
2677 &rradius, &ps.start_size, &ps.max_depth);
2678
2679 debug(("penrose: w%d h%d, tile size %d, start size %d, depth %d",
2680 width, height, tilesize, ps.start_size, ps.max_depth));
2681
2682 ps.new_tile = set_faces;
2683 ps.ctx = &sf_ctx;
2684
2685 max_faces = (width*3) * (height*3); /* somewhat paranoid... */
2686 max_dots = max_faces * 4; /* ditto... */
2687
2688 g = grid_empty();
2689 g->tilesize = tilesize;
2690 g->faces = snewn(max_faces, grid_face);
2691 g->dots = snewn(max_dots, grid_dot);
2692
2693 points = newtree234(grid_point_cmp_fn);
2694
2695 memset(&sf_ctx, 0, sizeof(sf_ctx));
2696 sf_ctx.g = g;
2697 sf_ctx.points = points;
2698
2699 if (desc != NULL) {
2700 if (sscanf(desc, "G%d,%d,%d", &xoff, &yoff, &aoff) != 3)
2701 assert(!"Invalid grid description.");
2702 } else {
2703 xoff = yoff = 0;
2704 }
2705
2706 xsz = width * tilesize;
2707 ysz = height * tilesize;
2708
2709 sf_ctx.xmin = xoff - xsz/2;
2710 sf_ctx.xmax = xoff + xsz/2;
2711 sf_ctx.ymin = yoff - ysz/2;
2712 sf_ctx.ymax = yoff + ysz/2;
2713
2714 debug(("penrose: centre (%f, %f) xsz %f ysz %f",
2715 0.0, 0.0, xsz, ysz));
2716 debug(("penrose: x range (%f --> %f), y range (%f --> %f)",
2717 sf_ctx.xmin, sf_ctx.xmax, sf_ctx.ymin, sf_ctx.ymax));
2718
2719 penrose(&ps, which, aoff);
2720
2721 freetree234(points);
2722 assert(g->num_faces <= max_faces);
2723 assert(g->num_dots <= max_dots);
2724
2725 debug(("penrose: %d faces total (equivalent to %d wide by %d high)",
2726 g->num_faces, g->num_faces/height, g->num_faces/width));
2727
2728 grid_trim_vigorously(g);
2729 grid_make_consistent(g);
2730
2731 /*
2732 * Centre the grid in its originally promised rectangle.
2733 */
2734 g->lowest_x -= ((sf_ctx.xmax - sf_ctx.xmin) -
2735 (g->highest_x - g->lowest_x)) / 2;
2736 g->highest_x = g->lowest_x + (sf_ctx.xmax - sf_ctx.xmin);
2737 g->lowest_y -= ((sf_ctx.ymax - sf_ctx.ymin) -
2738 (g->highest_y - g->lowest_y)) / 2;
2739 g->highest_y = g->lowest_y + (sf_ctx.ymax - sf_ctx.ymin);
2740
2741 return g;
2742 }
2743
2744 static void grid_size_penrose_p2_kite(int width, int height,
2745 int *tilesize, int *xextent, int *yextent)
2746 {
2747 grid_size_penrose(width, height, tilesize, xextent, yextent);
2748 }
2749
2750 static void grid_size_penrose_p3_thick(int width, int height,
2751 int *tilesize, int *xextent, int *yextent)
2752 {
2753 grid_size_penrose(width, height, tilesize, xextent, yextent);
2754 }
2755
2756 static grid *grid_new_penrose_p2_kite(int width, int height, char *desc)
2757 {
2758 return grid_new_penrose(width, height, PENROSE_P2, desc);
2759 }
2760
2761 static grid *grid_new_penrose_p3_thick(int width, int height, char *desc)
2762 {
2763 return grid_new_penrose(width, height, PENROSE_P3, desc);
2764 }
2765
2766 /* ----------- End of grid generators ------------- */
2767
2768 #define FNNEW(upper,lower) &grid_new_ ## lower,
2769 #define FNSZ(upper,lower) &grid_size_ ## lower,
2770
2771 static grid *(*(grid_news[]))(int, int, char*) = { GRIDGEN_LIST(FNNEW) };
2772 static void(*(grid_sizes[]))(int, int, int*, int*, int*) = { GRIDGEN_LIST(FNSZ) };
2773
2774 char *grid_new_desc(grid_type type, int width, int height, int dual, random_state *rs)
2775 {
2776 if (type != GRID_PENROSE_P2 && type != GRID_PENROSE_P3)
2777 return NULL;
2778
2779 return grid_new_desc_penrose(type, width, height, rs);
2780 }
2781
2782 char *grid_validate_desc(grid_type type, int width, int height, int dual, char *desc)
2783 {
2784 if (type != GRID_PENROSE_P2 && type != GRID_PENROSE_P3) {
2785 if (desc != NULL)
2786 return "Grid description strings not used with this grid type";
2787 return NULL;
2788 }
2789
2790 return grid_validate_desc_penrose(type, width, height, desc);
2791 }
2792
2793 grid *grid_new(grid_type type, int width, int height, int dual, char *desc)
2794 {
2795 char *err = grid_validate_desc(type, width, height, dual, desc);
2796 if (err) assert(!"Invalid grid description.");
2797
2798 if (!dual)
2799 {
2800 return grid_news[type](width, height, desc);
2801 }
2802 else
2803 {
2804 grid *temp;
2805 grid *g;
2806
2807 temp = grid_news[type](width, height, desc);
2808 g = grid_dual(temp);
2809 grid_free(temp);
2810 return g;
2811 }
2812 }
2813
2814 void grid_compute_size(grid_type type, int width, int height,
2815 int *tilesize, int *xextent, int *yextent)
2816 {
2817 grid_sizes[type](width, height, tilesize, xextent, yextent);
2818 }
2819
2820 /* ----------- End of grid helpers ------------- */
2821
2822 /* vim: set shiftwidth=4 tabstop=8: */