summaryrefslogtreecommitdiff
path: root/22.c
diff options
context:
space:
mode:
Diffstat (limited to '22.c')
-rw-r--r--22.c110
1 files changed, 103 insertions, 7 deletions
diff --git a/22.c b/22.c
index 60b2291..1b880bb 100644
--- a/22.c
+++ b/22.c
@@ -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;