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