static void sort_points (mc_point_t *A, int N) { int i, j; mc_point_t h, t; if (N <= 0) { return; } if (N == 1) { if (cmp_points (&A[0], &A[1]) > 0) { t = A[0]; A[0] = A[1]; A[1] = t; } return; } i = 0; j = N; h = A[j >> 1]; do { while (cmp_points (&A[i], &h) < 0) { i++; } while (cmp_points (&A[j], &h) > 0) { j--; } if (i <= j) { t = A[i]; A[i++] = A[j]; A[j--] = t; } } while (i <= j); sort_points (A+i, N-i); sort_points (A, j); }
int partition(struct Point a[], int l, int r) { int i, j; struct Point t, pivot; pivot = a[l]; i = l; j = r + 1; while (1) { do ++i; while (cmp_points(&a[i], &pivot, NULL) < 1 && i <= r); do --j; while (cmp_points(&a[j], &pivot, NULL) == 1); if (i >= j) break; if (a[i].line1 != NULL) { if (a[i].line1->p1 == &a[i]) a[i].line1->p1 = &a[j]; else a[i].line1->p2 = &a[j]; } if (a[j].line1 != NULL) { if (a[j].line1->p1 == &a[j]) a[j].line1->p1 = &a[i]; else a[j].line1->p2 = &a[i]; } if (a[i].line2 != NULL) { if (a[i].line2->p1 == &a[i]) a[i].line2->p1 = &a[j]; else a[i].line2->p2 = &a[j]; } if (a[j].line2 != NULL) { if (a[j].line2->p1 == &a[j]) a[j].line2->p1 = &a[i]; else a[j].line2->p2 = &a[i]; } t = a[i]; a[i] = a[j]; a[j] = t; } if (a[l].line1 != NULL) { if (a[l].line1->p1 == &a[l]) a[l].line1->p1 = &a[j]; else a[l].line1->p2 = &a[j]; } if (a[j].line1 != NULL) { if (a[j].line1->p1 == &a[j]) a[j].line1->p1 = &a[l]; else a[j].line1->p2 = &a[l]; } if (a[l].line2 != NULL) { if (a[l].line2->p1 == &a[l]) a[l].line2->p1 = &a[j]; else a[l].line2->p2 = &a[j]; } if (a[j].line2 != NULL) { if (a[j].line2->p1 == &a[j]) a[j].line2->p1 = &a[l]; else a[j].line2->p2 = &a[l]; } t = a[l]; a[l] = a[j]; a[j] = t; return j; }
/** for all points initiate their vis line to the one directly below */ void init_vis(struct Point *points, int num_points, struct Line *lines, int num_lines) { int i; double d; struct avl_table *tree = avl_create(cmp_points, NULL, NULL); struct avl_traverser it; struct Point *p; double y1, y2; struct Point *s1, *s2; for (i = 0; i < num_points; i++) { points[i].vis = NULL; d = PORT_DOUBLE_MAX; avl_t_init(&it, tree); /* loop through the tree */ while ((p = avl_t_next(&it)) != NULL) { if (segment1(p) == NULL && segment2(p) == NULL) continue; /* test for intersection and get the intersecting point */ if (segment1(p) != NULL && segment_intersect(segment1(p), &points[i], &y1) > -1) { /* find the closest one below */ if (y1 < points[i].y && (points[i].y - y1) < d) { d = points[i].y - y1; points[i].vis = segment1(p); } } if (segment2(p) != NULL && segment_intersect(segment2(p), &points[i], &y2) > -1) { if (y2 < points[i].y && (points[i].y - y2) < d) { d = points[i].y - y2; points[i].vis = segment2(p); } } } /* end loop */ s1 = s2 = NULL; /* now if the other point is on the right, we can delete it */ if (segment1(&points[i]) != NULL && cmp_points(&points[i], other1(&points[i]), NULL) > 0) { p = other1(&points[i]); /* unless the other point of it is on the left */ if (segment1(p) != NULL && other1(p) != &points[i] && cmp_points(&points[i], other1(p), NULL) > 0) s1 = avl_delete(tree, p); else if (segment2(p) != NULL && other2(p) != &points[i] && cmp_points(&points[i], other2(p), NULL) > 0) s1 = avl_delete(tree, p); } /* now if the other point is on the right, we can delete it */ if (segment2(&points[i]) != NULL && cmp_points(&points[i], other2(&points[i]), NULL) > 0) { p = other2(&points[i]); /* unless the other point of it is on the left */ if (segment1(p) != NULL && other1(p) != &points[i] && cmp_points(&points[i], other1(p), NULL) > 0) s2 = avl_delete(tree, p); else if (segment2(p) != NULL && other2(p) != &points[i] && cmp_points(&points[i], other2(p), NULL) > 0) s2 = avl_delete(tree, p); } /* if both weren't deleted, it means there is at least one other point on the left, so add the current */ /* also there is no point adding the point if there is no segment attached to it */ if ((s1 == NULL || s2 == NULL)) { avl_insert(tree, &points[i]); } } avl_destroy(tree, NULL); }