static void convexhull_delete_circumference_rectangles(dlist_t *circumrects) { dlink_t *a; assert(circumrects); while (circumrects->count > 0) { a = dlist_extract(circumrects); polygon_destroy((polygon_t *)a->object); dlink_destroy(a); } }
point_t *point_list_pop(point_list_t *list) { dlink_t *link; point_t *p; assert(list); link = dlist_pop((dlist_t *)list); p = (point_t *)link->object; point_dec_ref(p); dlink_destroy(link); return p; }
line_t *line_list_pop(line_list_t *list) { dlink_t *link; line_t *line; assert(list); link = dlist_pop((dlist_t *)list); line = (line_t *)link->object; line_dec_ref(line); dlink_destroy(link); return line; }
point_t *point_list_pick(int i, point_list_t *list) { dlink_t *link; point_t *p; assert(list); assert(0 <= i && i < point_list_get_count(list)); link = dlist_pick(i, (dlist_t *)list); p = (point_t *)link->object; point_dec_ref(p); dlink_destroy(link); return p; }
line_t *line_list_pick(int i, line_list_t *list) { dlink_t *link; line_t *line; assert(list); assert(i >= 0 && i < line_list_get_count(list)); link = dlist_pick(i, (dlist_t *)list); line = (line_t *)link->object; line_dec_ref(line); dlink_destroy(link); return line; }
void point_list_destroy(point_list_t *list) { dlink_t *link; assert(list); if (point_list_get_ref(list) <= 0) { while (point_list_get_count(list) > 0) { link = dlist_pop((dlist_t *)list); point_destroy((point_t *)link->object); dlink_destroy(link); } dlist_destroy((dlist_t *)list); } else { list->reference--; } }
/* void line_list_delete(line_list_t *list) { dlink_t *link; line_t *line; assert(list); for (link = list->tail->next; link != list->head; link = link->next) { line = (line_t *)link->object; line_(line); } } */ void line_list_destroy(line_list_t *list) { dlink_t *link; assert(list); if (line_list_get_ref(list) <= 0) { while (line_list_get_count(list) > 0) { link = dlist_pop((dlist_t *)list); line_destroy((line_t *)link->object); dlink_destroy(link); } dlist_destroy((dlist_t *)list); } else { line_list_dec_ref(list); } }
/* -------------------------------------------------------------------------- * * Behandelt alle Ereignisse innerhalb der Kartenkonfiguration * * -------------------------------------------------------------------------- */ int ui_config_card_proc(sgWidget *widget, sgEvent event) { /* Allgemeine Ereignisbehandlung (für sound und so) */ ui_generic_proc(widget, event); if(event == SG_EVENT_CHANGE) { /* Wenn die Rahmenstärke geändert hat, dann den Wert temporär in die Kartenconfig schreiben und die Vorschau neu zeichnen */ if(widget == ui_config_card_border) { card_config.border = sgGetAdjustValue(ui_config_card_border, NULL) * 255 / 5; ui_config_card_redraw |= CARD_RENDER; } /* Wenn der Zoomfaktor geändert hat, dann den Wert temporär in die Kartenconfig schreiben und die Vorschau neu zeichnen */ if(widget == ui_config_card_zoom) { card_config.zoom = sgGetAdjustValue(ui_config_card_zoom, NULL); ui_config_card_redraw |= CARD_RENDER; } /* Wenn Kartenfarbe geändert hat, dann diese neu setzen: */ /* Farbton hat geändert */ if(widget == ui_config_card_hue) { sgColor color; sgHSV hsv; hsv = sgGetColorSelHSV(ui_config_card_hue); color = sgHSVToRGB(hsv); card_tint.r = color.r; card_tint.g = color.g; card_tint.b = color.b; ui_config_card_redraw |= CARD_RENDER; if(ui_config_card_sat) sgSetColorSelHue(ui_config_card_sat, hsv.h); if(ui_config_card_val) sgSetColorSelHue(ui_config_card_val, hsv.h); } /* Sättigung hat geändert */ if(widget == ui_config_card_sat) { sgColor color; sgHSV hsv; hsv = sgGetColorSelHSV(ui_config_card_sat); color = sgHSVToRGB(hsv); card_tint.r = color.r; card_tint.g = color.g; card_tint.b = color.b; ui_config_card_redraw |= CARD_RENDER; if(ui_config_card_hue) sgSetColorSelSaturation(ui_config_card_hue, hsv.s); if(ui_config_card_val) sgSetColorSelSaturation(ui_config_card_val, hsv.s); } /* Helligkeit hat geändert */ if(widget == ui_config_card_val) { sgColor color; sgHSV hsv; hsv = sgGetColorSelHSV(ui_config_card_val); color = sgHSVToRGB(hsv); card_tint.r = color.r; card_tint.g = color.g; card_tint.b = color.b; ui_config_card_redraw |= CARD_RENDER; if(ui_config_card_hue) sgSetColorSelValue(ui_config_card_hue, hsv.v); if(ui_config_card_sat) sgSetColorSelValue(ui_config_card_sat, hsv.v); } /* Transparenz hat geändert */ if(widget == ui_config_card_transparency) { card_tint.a = 255 - (sgGetAdjustValue(ui_config_card_transparency, NULL) * 255 / 100); ui_config_card_redraw |= CARD_RENDER; } } if(event == SG_EVENT_CLICK) { /* ..andere Karte wurde verlangt? */ if(widget == ui_config_card_pick) { struct list list; /* Eine Liste mit der aktuellen Karte machen, damit diese nicht wieder gewählt wird */ dlink_list_zero(&list); dlink_add_head(&list, dlink_node_new(), ui_config_card_card); /* Alte Kartendaten freigeben */ card_clean(ui_config_card_card); /* Neue Karte ziehen und redraw */ ui_config_card_card = card_random(&list); ui_config_card_redraw |= CARD_RENDER; /* Liste wieder freigeben */ dlink_destroy(&list); } /* Karte hervorheben in der Vorschau? */ if(widget == ui_config_card_hilite) ui_config_card_redraw |= CARD_RENDER; /* Karte auswählen in der Vorschau? */ if(widget == ui_config_card_select) ui_config_card_redraw |= CARD_RENDER; } return 0; }
/* some problem is occurred due to co-linear pixels, * so it need to be check the maximum distance within same minimum angle * comment : if break statement in the Right chain growth routine is converted * from "if (ycoord[imin] < ycoord[i-1]) break;" * to "if (ycoord[imin] <= ycoord[i-1]) break;" * , then some problem is removed. * However, if an point exits * such that is resemble to "ycoord" of the extreme point * and has the minimum angle * then the convex hull that we want don't be created. */ static int jarvismarch(polygon_t *chull, point_list_t *points) { real_t ang, dist, ymin; real_t amin, dmax, dx, dy; dlink_t *x, *y, *ax, *bx; point_t *p, *q; assert(chull); assert(points); assert(point_list_get_count(points) >= 3); // Preparing the polygon, and // Find the point with minimum value of y-coordinate for (ax = NULL, x = points->tail->next; x != points->head; x = x->next) { p = (point_t *)x->object; y = dlink_new(); point_inc_ref(p); y->object = (void *)p; dlist_insert(y, chull); if (ax == NULL || point_get_y(p) < ymin) { ax = y; ymin = point_get_y(p); } } dlink_cutoff(ax); dlist_dec_count(chull); dlist_push(ax, chull); point_dump((point_t *)ax->object); // Scan right chain for (ax = chull->tail->next; ax->next != chull->head; ax = ax->next) { p = (point_t *)ax->object; for (bx = NULL, x = ax->next; x != chull->head; x = x->next) { q = (point_t *)x->object; dx = point_get_x(q) - point_get_x(p); dy = point_get_y(q) - point_get_y(p); ang = arctan2r(dy, dx); dist = sqrt(sqr(dx) + sqr(dy)); // Find another vertex with min-angle and max-distance if (bx == NULL || ang < amin) { bx = x; amin = ang; dmax = dist; } else if (ang == amin && dist > dmax) { bx = x; dmax = dist; } } q = (point_t *)bx->object; // Right chain complete ? if (point_get_y(q) < point_get_y(p)) break; // Swapping (coordinations and mark) dlink_cutoff(bx); dlink_append(bx, ax); point_dump((point_t *)bx->object); } //printf("n: %d\n", convexhull->count); // Scan left chain for (; ax->next != chull->head; ax = ax->next) { p = (point_t *)ax->object; for (bx = NULL, x = ax->next; x != chull->head; x = x->next) { q = (point_t *)x->object; dx = point_get_x(p) - point_get_x(q); dy = point_get_y(p) - point_get_y(q); ang = arctan2r(dy, dx); dist = sqrt(sqr(dx) + sqr(dy)); if (bx == NULL || ang < amin) { bx = x; amin = ang; dmax = dist; } else if (ang == amin && dist > dmax) { bx = x; dmax = dist; } } y = chull->tail->next; q = (point_t *)y->object; dx = point_get_x(p) - point_get_x(q); dy = point_get_y(p) - point_get_y(q); ang = arctan2r(dy, dx); // Convexhull complete ? if (ang < amin) break; // Swapping dlink_cutoff(bx); dlink_append(bx, ax); point_dump((point_t *)bx->object); } //printf("n: %d\n", convexhull->count); while (ax->next != chull->head) { x = ax->next; dlink_cutoff(x); dlist_dec_count(chull); point_destroy((point_t *)x->object); dlink_destroy(x); } return dlist_get_count(chull); }
static int quickhull(polygon_t *chull, point_list_t *points) { real_t ymin, ymax, yval; point_t *p, *v1, *v2, *v3; dlink_t *ax, *bx, *x, *y, *next; dlist_t *right_group, *left_group; assert(chull); assert(points); // Allocate the structure element of convex hull for (x = points->tail->next; x != points->head; x = x->next) { p = (point_t *)x->object; point_inc_ref(p); y = dlink_new(); y->object = (void *)p; dlist_insert(y, chull); } // find the extreme points along y-axis ax = NULL; bx = NULL; for (x = chull->tail->next; x != chull->head; x = x->next) { yval = point_get_y((point_t *)(x->object)); if (ax == NULL || yval < ymin) { ax = x; ymin = yval; } if (bx == NULL || yval > ymax) { bx = x; ymax = yval; } } dlink_cutoff(ax); dlist_dec_count(chull); dlink_cutoff(bx); dlist_dec_count(chull); //point_dump((point_t *)ax->object); //point_dump((point_t *)bx->object); v1 = point_new(); v2 = point_new(); v3 = point_new(); //printf("for right section\n"); right_group= dlist_new(); dlist_insert(ax, right_group); point_subtract(v2, (point_t *)bx->object, (point_t *)ax->object); for (x = chull->tail->next; x != chull->head;) { //point_dump((point_t *)x->object); point_subtract(v1, (point_t *)x->object, (point_t *)ax->object); point_xproduct(v3, v1, v2); if (point_get_z(v3) > 0) { next = x->next; dlink_cutoff(x); dlist_dec_count(chull); dlist_insert(x, right_group); //printf(" "); //point_dump((point_t *)x->object); x = next; } else x = x->next; } dlist_insert(bx, right_group); quickhull_grouping(right_group); //printf("for left section\n"); ax = dlist_pop(right_group); bx = dlist_extract(right_group); //point_dump((point_t *)ax->object); //point_dump((point_t *)bx->object); left_group = dlist_new(); dlist_insert(bx, left_group); point_subtract(v2, (point_t *)ax->object, (point_t *)bx->object); for (x = chull->tail->next; x != chull->head; ) { point_subtract(v1, (point_t *)x->object, (point_t *)bx->object); point_xproduct(v3, v1, v2); if (point_get_z(v3) > 0) { next = x->next; dlink_cutoff(x); dlist_dec_count(chull); dlist_insert(x, left_group); //point_dump((point_t *)x->object); x = next; } else { next = x->next; dlink_cutoff(x); dlist_dec_count(chull); point_destroy((point_t *)x->object); dlink_destroy(x); x = next; } } dlist_insert(ax, left_group); quickhull_grouping(left_group); ax = dlist_extract(left_group); bx = dlist_pop(left_group); dlist_insert(ax, chull); while (dlist_get_count(right_group) > 0) { x = dlist_pop(right_group); dlist_insert(x, chull); } dlist_insert(bx, chull); while (dlist_get_count(left_group) > 0) { x = dlist_pop(left_group); dlist_insert(x, chull); } dlist_destroy(left_group); dlist_destroy(right_group); point_destroy(v3); point_destroy(v2); point_destroy(v1); return dlist_get_count(chull); }
/* * Quick-Hull * Here's an algorithm that deserves its name. * It's a fast way to compute the convex hull of a set of points on the plane. * It shares a few similarities with its namesake, quick-sort: * - it is recursive. * - each recursive step partitions data into several groups. * * The partitioning step does all the work. The basic idea is as follows: * 1. We are given a some points, * and line segment AB which we know is a chord of the convex hull. * 2. Among the given points, find the one which is farthest from AB. * Let's call this point C. * 3. The points inside the triangle ABC cannot be on the hull. * Put them in set s0. * 4. Put the points which lie outside edge AC in set s1, * and points outside edge BC in set s2. * * Once the partitioning is done, we recursively invoke quick-hull on sets s1 and s2. * The algorithm works fast on random sets of points * because step 3 of the partition typically discards a large fraction of the points. */ static int quickhull_grouping(dlist_t *group) { dlink_t *x, *ax, *bx, *cx, *next; dlist_t *s1, *s2; point_t *v1, *v2, *v3; real_t area; assert(group); if (dlist_get_count(group) <= 2) return dlist_get_count(group); v1 = point_new(); v2 = point_new(); v3 = point_new(); // Find the point with maximum parallelogram's area ax = dlist_pop(group); bx = dlist_extract(group); cx = NULL; point_subtract(v2, (point_t *)(bx->object), (point_t *)(ax->object)); for (x = group->tail->next; x != group->head; x = x->next) { point_subtract(v1, (point_t *)(x->object), (point_t *)(ax->object)); point_xproduct(v3, v1, v2); if (cx == NULL || point_get_z(v3) > area) { cx = x; area = point_get_z(v3); } } dlink_cutoff(cx); dlist_dec_count(group); // S1 grouping s1 = dlist_new(); dlist_insert(ax, s1); point_subtract(v2, (point_t *)(cx->object), (point_t *)(ax->object)); for (x = group->tail->next; x != group->head; ) { point_subtract(v1, (point_t *)(x->object), (point_t *)(ax->object)); point_xproduct(v3, v1, v2); if (point_get_z(v3) > 0) { next = x->next; dlink_cutoff(x); dlist_dec_count(group); dlist_insert(x, s1); x = next; } else x = x->next; } dlist_insert(cx, s1); quickhull_grouping(s1); assert(cx == s1->head->prev); // S2 grouping and pop out others cx = dlist_extract(s1); s2 = dlist_new(); dlist_insert(cx, s2); point_subtract(v2, (point_t *)bx->object, (point_t *)cx->object); for (x = group->tail->next; x != group->head;) { point_subtract(v1, (point_t *)x->object, (point_t *)cx->object); point_xproduct(v3, v1, v2); if (point_get_z(v3) > 0) { next = x->next; dlink_cutoff(x); dlist_dec_count(group); dlist_insert(x, s2); x = next; } else { next = x->next; dlink_cutoff(x); dlist_dec_count(group); point_destroy((point_t *)x->object); dlink_destroy(x); x = next; } } dlist_insert(bx, s2); quickhull_grouping(s2); assert(bx == s2->head->prev); assert(dlist_get_count(group) == 0); //assert(group->count == 0); // Merge s1 and s2 into group while (dlist_get_count(s1) > 0) { x = dlist_pop(s1); dlist_insert(x, group); } while (dlist_get_count(s2) > 0) { x = dlist_pop(s2); dlist_insert(x, group); } dlist_destroy(s2); dlist_destroy(s1); point_destroy(v3); point_destroy(v2); point_destroy(v1); return dlist_get_count(group); }
/* Graham's Scan * Given a set of points on the plane, Graham's scan computes their convex hull. * The algorithm works in three phases: * 1. Find an extreme point. * This point will be the pivot, is guaranteed to be on the hull, * and is chosen to be the point with largest y coordinate. * 2. Sort the points in order of increasing angle about the pivot. * We end up with a star-shaped polygon (one in which one special point, * in this case the pivot, can "see" the whole polygon). * 3. Build the hull, by marching around the star-shaped poly, adding edges * when we make a left turn, and back-tracking when we make a right turn. */ static int grahamscan(polygon_t *chull, point_list_t *points) { int i; real_t dx, dy, ymin; real_t *ang; point_t *p, *q; point_t *v1, *v2, *v3; dlink_t *ax, *bx, *cx, *x, *y, *tmp; assert(chull); assert(points); assert(point_list_get_count(points) >= 3); ang = (real_t *)malloc(point_list_get_count(points) * sizeof(real_t)); assert(ang); // Find an extreme point // Preparing the polygon, and // Find the point with minimum value of y-coordinate for (ax = NULL, x = points->tail->next; x != points->head; x = x->next) { p = (point_t *)x->object; y = dlink_new(); point_inc_ref(p); y->object = (void *)p; dlist_insert(y, chull); if (ax == NULL || point_get_y(p) < ymin) { ax = y; ymin = point_get_y(p); } } dlink_cutoff(ax); dlist_dec_count(chull); dlist_push(ax, chull); // Sort the points in order of increasing angle about the pivot. p = (point_t *)ax->object; //point_dump(p); for (i = 0, x = ax->next; x != chull->head; x = x->next) { q = (point_t *)x->object; dx = point_get_x(q) - point_get_x(p); dy = point_get_y(q) - point_get_y(p); ang[i] = arctan2r(dy, dx); x->spare = (void *)&(ang[i]); i++; //point_dump(q); //printf("ang: %lf\n", ang[i-1]); } for (x = ax->next; x->next != chull->head; x = x->next) { for (y = x->next; y != chull->head; y = y->next) { if (*((real_t *)y->spare) < *((real_t *)x->spare)) { dlink_exchange(x, y); tmp = x, x = y, y = tmp; } } } //point_dump((point_t *)c->object); v1 = point_new(); v2 = point_new(); v3 = point_new(); cx = chull->tail->next->next->next; while (cx != chull->head) { bx = cx->prev; ax = bx->prev; point_subtract(v1, (point_t *)ax->object, (point_t *)bx->object); point_subtract(v2, (point_t *)cx->object, (point_t *)bx->object); point_xproduct(v3, v1, v2); // Convex ? if (point_get_z(v3) < 0) { cx = cx->next; } else { dlink_cutoff(bx); dlist_dec_count(chull); point_destroy((point_t *)bx->object); dlink_destroy(bx); } } for (x = chull->tail->next; x != chull->head; x = x->next) x->spare = NULL; point_destroy(v3); point_destroy(v2); point_destroy(v1); free(ang); return dlist_get_count(chull); }