diff options
Diffstat (limited to '22.c')
-rw-r--r-- | 22.c | 110 |
1 files changed, 103 insertions, 7 deletions
@@ -162,17 +162,118 @@ point_init(struct point * pt, int x, int y) } +struct face { + struct point vertices[4]; + enum direction dir; // The orientation of the face (as in faceids[]) +}; + + +struct face * +face_init(struct face * face, struct point const * bl, struct point const * tr, + enum direction dir) +{ + if (bl->x >= tr->x || bl->y >= tr->y) + return NULL; + + point_init(face->vertices + 0, bl->x, bl->y); + point_init(face->vertices + 1, tr->x, bl->y); + point_init(face->vertices + 2, tr->x, tr->y); + point_init(face->vertices + 3, bl->x, tr->y); + face->dir = dir; + return face; +} + + struct map { char * _buf; int cols; int rows; enum map_type type; + struct face faces[6]; }; +int map_elem(struct map const * map, int x, int y); + int map_outline(struct point ** outline, struct map const * map); +int +map__init_faces(struct map * map) +{ + struct point * outline, * ol, min, max, pt; + int len, nfaces; + + if ((len = map_outline(&outline, map)) < 0) { + return -1; + } + + // Find the limits of the outline + ol = outline; + point_init(&min, ol->x, ol->y); + point_init(&max, ol->x, ol->y); + for (++ol; ol < outline + len - 1; ++ol) { + if (ol->x < min.x) + min.x = ol->x; + if (ol->x > max.x) + max.x = ol->x; + if (ol->y < min.y) + min.y = ol->y; + if (ol->x > max.x) + max.y = ol->y; + } + + // Go through all combinations of x and y coordinates in the outline, + // find pairs that are the bottom-left corners of faces, and create + // faces out of them. + nfaces = 0; + pt = min; + while (pt.y != max.y) { + struct point next; + + // Find the "next" individual x and y coords in the outline + next = max; + for (ol = outline; ol < outline + len - 1; ++ol) { + if (ol->x > pt.x && ol->x < next.x) + next.x = ol->x; + if (ol->y > pt.y && ol->y < next.y) + next.y = ol->y; + } + + // Is the current point a face? + if (map_elem(map, pt.x, pt.y) != ' ') { + if (nfaces == 6) { + fprintf(stderr, "%s: Already %d faces at %d,%d\n", + __FUNCTION__, nfaces, pt.x, pt.y); + free(outline); + return -1; + } + // Set to north for now. Will change later. + face_init(map->faces + nfaces, &pt, &next, D_NORTH); + ++nfaces; + } + + // Try the next candidate point + pt.x = next.x; + if (pt.x == max.x) { + pt.x = min.x; + pt.y = next.y; + } + } + if (nfaces != 6) { + // TODO: Add face-splitting logic here, to account for e.g. + // T-shaped nets, where we don't have outline corners to tell + // us where the faces are. + fprintf(stderr, "%s: Only %d faces\n", __FUNCTION__, nfaces); + free(outline); + return -1; + } + + free(outline); + return 0; +} + + // Initialise a map from a buffer. // // The map takes ownership of the buffer from when it's called, whether @@ -219,17 +320,12 @@ map_init(struct map * map, char * buf, size_t buflen, enum map_type type) } if (map->type == M_NET) { - struct point * outline; - int len; - - if ((len = map_outline(&outline, map)) < 0) { + if (map__init_faces(map) != 0) { free(map->_buf); return NULL; } - fprintf(stderr, "Outline has %d corners\n", len - 1); - - free(outline); + fprintf(stderr, "Faces initialised\n"); } return map; |