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.
This commit is contained in:
Ben Harris 2017-07-18 00:14:20 +01:00
parent 563205261f
commit c56e10dc09

View File

@ -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;
}
}