From: Ben Harris Date: Mon, 17 Jul 2017 23:14:20 +0000 (+0100) Subject: Further cleanup of skeleton paths. X-Git-Tag: bedstead-002.000~126 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~bjharris/git?a=commitdiff_plain;h=c56e10dc09b538589ad4e8ca4a9bbf42f39089fe;p=bedstead.git Further cleanup of skeleton paths. The cleanup itself is good, but emit_paths() will need enhancement. At the moment, it assumes that all paths are closed, so it doesn't matter where on a path it starts emitting it. With an open path, though, it's important to emit it starting at one end, so there will have to be a mechanism for distinguishing open from closed paths and behaving accordingly. --- diff --git a/bedstead.c b/bedstead.c index f47f521..8499a66 100644 --- a/bedstead.c +++ b/bedstead.c @@ -1898,10 +1898,34 @@ dochar(char const data[YSIZE], unsigned flags) emit_path(); } +static void +reverse_path(point *a) +{ + point *tmp; + + while (a->prev != NULL) + a = a->prev; + while (a != NULL) { + tmp = a->next; + a->next = a->prev; + a->prev = tmp; + a = tmp; + } +} + /* Join together two points each at the end of a path */ static void join_ends(point *a, point *b) { + point *tmp; + + if (a->prev == NULL && b->next == NULL) { + tmp = a; a = b; b = tmp; + } + if (a->prev == NULL) + reverse_path(a); + if (b->next == NULL) + reverse_path(b); assert(a->next == NULL); assert(a->prev != NULL); assert(b->prev == NULL); @@ -1910,7 +1934,7 @@ join_ends(point *a, point *b) a->next = b; b->prev = a; fix_identical(a); /* Will delete a */ - fix_collinear(b); /* Will delete b */ + fix_collinear(b); /* Might delete b */ } static bool @@ -1919,23 +1943,44 @@ point_endp(point *p) return p->next == NULL || p->prev == NULL; } +static bool +point_deadp(point *p) +{ + return p->next == NULL && p->prev == NULL; +} + static void clean_skeleton() { int i, j; + /* Pass 1: join collinear connected segments */ for (i = 0; i < nextpoint; i++) { - if (points[i].prev == NULL && points[i].next == NULL) + if (point_deadp(&points[i])) continue; for (j = 0; j < nextpoint; j++) { - if (points[j].prev == NULL && points[j].next == NULL) + if (point_deadp(&points[j])) continue; if (vec_eqp(points[i].v, points[j].v) && points[i].next == NULL && points[j].prev == NULL && vec_inline3(points[i].prev->v, points[i].v, points[j].next->v)) join_ends(&points[i], &points[j]); - if (points[i].prev == NULL && points[i].next == NULL) + if (point_deadp(&points[i])) + break; + } + } + /* Pass 2: join any connected segments */ + for (i = 0; i < nextpoint; i++) { + if (point_deadp(&points[i])) + continue; + for (j = i+1; j < nextpoint; j++) { + if (point_deadp(&points[j])) + continue; + if (vec_eqp(points[i].v, points[j].v) && + point_endp(&points[i]) && point_endp(&points[j])) + join_ends(&points[i], &points[j]); + if (point_deadp(&points[i])) break; } }