int main (int argc, char **argv) { PolygonView *view; polygon_t *polygon = NULL; GtkWidget *window; FILE *file; char *line = NULL; size_t len = 0; gtk_init (&argc, &argv); view = g_object_new (polygon_view_get_type (), NULL); file = fopen (argv[1], "r"); if (file != NULL) { while (getline (&line, &len, file) != -1) { point_t p1, p2; double top, bottom; int dir; if (strncmp (line, "polygon: ", sizeof("polygon: ")-1) == 0) { if (polygon && polygon->num_edges) { g_print ("read polygon with %d edges\n", polygon->num_edges); polygon = polygon_new (view); } else if (polygon == NULL) polygon = polygon_new (view); } else if (sscanf (line, " [%*d] = [(%lf, %lf), (%lf, %lf)], top=%lf, bottom=%lf, dir=%d", &p1.x, &p1.y, &p2.x, &p2.y, &top, &bottom, &dir) == 7) { polygon = _polygon_add_edge (view, polygon, &p1, &p2, top, bottom, dir); } } if (polygon && polygon->num_edges) g_print ("read polygon with %d edges\n", polygon->num_edges); g_print ("extents=(%lg, %lg), (%lg, %lg)\n", view->extents.p1.x, view->extents.p1.y, view->extents.p2.x, view->extents.p2.y); fclose (file); } if (argc > 2) highlight = atof (argv[2]); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_set_size_request (window, 800, 800); gtk_container_add (GTK_CONTAINER (window), &view->widget); gtk_widget_show_all (window); gtk_main (); return 0; }
polygon_t* polygon_giftwrap(point_t* points, int num_points) { ASSERT(num_points > 2); ASSERT(all_points_are_coplanar(points, num_points)); // Find the plane of the polygon. vector_t normal; compute_normal(points, num_points, &normal); point_t x0; compute_centroid(points, num_points, &x0); sp_func_t* plane = plane_new(&normal, &x0); // Do the gift-wrapping in 2D. point2_t pts[num_points]; for (int i = 0; i < num_points; ++i) plane_project(plane, &points[i], &pts[i]); polygon2_t* poly2 = polygon2_giftwrap(pts, num_points); #if 0 // Re-embed the resulting vertices in 3D. int num_vertices = polygon2_num_vertices(poly2); point_t vertices[num_vertices]; int pos = 0, offset = 0; point2_t* vtx; while (polygon2_next_vertex(poly2, &pos, &vtx)) plane_embed(plane, vtx, &vertices[offset++]); #endif // Read off the vertex ordering from the planar polygon. Note that // not all of the vertices will be used in general. int num_p2_points = polygon2_num_vertices(poly2); int* ordering = polygon2_ordering(poly2); // Create our polygon with the given ordering. polygon_t* poly = NULL; if (num_p2_points < num_points) { point_t p2_points[num_p2_points]; for (int i = 0; i < num_p2_points; ++i) point_copy(&p2_points[i], &points[ordering[i]]); poly = polygon_new(p2_points, num_p2_points); } else poly = polygon_new_with_ordering(points, ordering, num_points); // Clean up. poly2 = NULL; plane = NULL; return poly; }
polygon_t* polygon_clone(polygon_t* poly) { return polygon_new(poly->vertices, poly->num_vertices); }
/* * By computing a formula, deriving and finding the minimum, * one can prove that * the minimum rects will always have at least one side that lies on a polygon edge. * In order to find the minimum area or circumference blocking rectangule, * we'll examine a sequence of such rectangles. * The basic idea is to start with a bounding rectangle and to rotate it at each step, * so we'll change only one point from the polygon's points that lie on the rect. * We do that by calculating the angles for each point * between the rect side that lies on it and the next polygon edge (clockwise). * We rotate the rect in the minimal angle we've calculated. * The first rect will lie on the most right, most left, most up and most down points. * For each rect we'll calculate the area and the circumference. This way we can find the minimum. */ static void convexhull_create_circumference_rectangles(dlist_t *circumrects, polygon_t *chull) { int i, irotate; real_t *angle, rectangle[4], delta; real_t rotate, dmin, slope, yslope, ortho, yortho, temp; real_t xmin, xmax, ymin, ymax, area; point_t *p, *q, *r, *s; dlink_t *left, *right, *top, *bottom; dlink_t *cross_vertex[4], *start, *pivot, *pivot_next; dlink_t *ax, *bx; polygon_t *rect; assert(circumrects); assert(chull); assert(polygon_get_count(chull) >= 3); // Finding angle of edge of convexhull angle = (real_t *)malloc(polygon_get_count(chull) * sizeof(real_t)); assert(angle); i = 0; ax = chull->head->prev; bx = chull->tail->next; do { p = (point_t *)ax->object; q = (point_t *)bx->object; angle[i] = arctan2r(point_get_y(q) - point_get_y(p), point_get_x(q) - point_get_x(p)); //angle[i] = angle[i] > M_PI ? angle[i]-M_PI : angle[i]; ax->spare = (void *)&angle[i]; printf("(%lf,%lf)->(%lf,%lf):%lf\n", point_get_x(p), point_get_y(p), point_get_x(q), point_get_y(q), angle[i] * 180 / M_PI); i++; ax = bx; bx = bx->next; } while (bx != chull->head); printf("Initialized the angle between verteces\n"); // Finding four extreme points left = NULL; right = NULL; top = NULL; bottom = NULL; for (ax = chull->tail->next; ax != chull->head; ax = ax->next) { p = (point_t *)ax->object; if (left == NULL || point_get_x(p) < xmin) { left = ax; xmin = point_get_x(p); } if (right == NULL || point_get_x(p) > xmax) { right = ax; xmax = point_get_x(p); } if (bottom == NULL || point_get_y(p) < ymin) { bottom = ax; ymin = point_get_y(p); } if (top == NULL || point_get_y(p) > ymax) { top = ax; ymax = point_get_y(p); } } cross_vertex[0] = bottom; cross_vertex[1] = right; cross_vertex[2] = top; cross_vertex[3] = left; area = (xmax - xmin) * (ymax - ymin); // Forming the starting rectangle from four extreme points rect = polygon_new(); polygon_insert(point_new_and_set(xmin, ymin, 0), rect); polygon_insert(point_new_and_set(xmax, ymin, 0), rect); polygon_insert(point_new_and_set(xmax, ymax, 0), rect); polygon_insert(point_new_and_set(xmin, ymax, 0), rect); // Angle of four edge of the starting rectangle rectangle[0] = 0; rectangle[1] = M_PI_2; rectangle[2] = M_PI; rectangle[3] = M_PI + M_PI_2; for (i = 0, ax = rect->tail->next; ax != rect->head; ax = ax->next) { ax->spare = (void *)&rectangle[i]; i++; } ax = dlink_new(); ax->object = (void *)polygon_new_and_copy(rect); dlist_insert(ax, circumrects); // Difference between angle of edge of rectangle and edge of convexhull start = NULL; for (i = 0, ax = rect->tail->next; ax != rect->head; ax = ax->next) { delta = (*((real_t *)cross_vertex[i]->spare) - *((real_t *)ax->spare) + 2 * M_PI); if (delta >= 2 * M_PI) delta -= 2 * M_PI; if ((start == NULL) || (delta < dmin)) { start = cross_vertex[i]; dmin = delta; irotate = i; } i++; } rotate = 0; pivot = start; do { if (pivot->next == chull->head) pivot_next = chull->tail->next; else pivot_next = pivot->next; p = (point_t *)pivot->object; q = (point_t *)pivot_next->object; if (point_get_x(p) == point_get_x(q) || point_get_y(p) == point_get_y(q)) { // For 0 or 90 or 180 degree // Nothing } else { // For others // Update rectangluar by pivot edge for rotation // Finding parameters of extending line between p and q ///////////////////////////////////////////////////////// slope = (point_get_y(q) - point_get_y(p)) / (point_get_x(q) - point_get_x(p)); yslope = point_get_y(q) - slope * point_get_x(q); r = (point_t *)cross_vertex[(irotate + 1) % 4]->object; ortho = -1 / slope; yortho = point_get_y(r) - ortho * point_get_x(r); s = polygon_glimpse(irotate, rect); point_put_x(-1 * (yslope - yortho) / (slope - ortho), s); point_put_y(slope * point_get_x(s) + yslope, s); ///////////////////////////////////////////////////////// temp = slope; slope = ortho; ortho = temp; yslope = yortho; r = (point_t *)cross_vertex[(irotate + 2) % 4]->object; yortho = point_get_y(r) - ortho * point_get_x(r); s = polygon_glimpse((irotate + 1) % 4, rect); point_put_x(-1 * (yslope - yortho) / (slope - ortho), s); point_put_y(slope * point_get_x(s) + yslope, s); ///////////////////////////////////////////////////////// temp = slope; slope = ortho; ortho = temp; yslope = yortho; r = (point_t *)cross_vertex[(irotate + 3) % 4]->object; yortho = point_get_y(r) - ortho * point_get_x(r); s = polygon_glimpse((irotate + 2) % 4, rect); point_put_x(-1 * (yslope - yortho) / (slope - ortho), s); point_put_y(slope * point_get_x(s) + yslope, s); ///////////////////////////////////////////////////////// temp = slope; slope = ortho; ortho = temp; yslope = yortho; r = (point_t *)cross_vertex[irotate]->object; yortho = point_get_y(r) - ortho * point_get_x(r); s = polygon_glimpse((irotate + 3) % 4, rect); point_put_x(-1 * (yslope - yortho) / (slope - ortho), s); point_put_y(slope * point_get_x(s) + yslope, s); ///////////////////////////////////////////////////////// rotate += dmin; for (ax = rect->tail->next; ax != rect->head; ax = ax->next) { *((real_t *)ax->spare) += dmin; if (*((real_t *)ax->spare) >= 2 * M_PI) *((real_t *)ax->spare) -= 2 * M_PI; } p = polygon_glimpse(0, rect); q = polygon_glimpse(1, rect); r = polygon_glimpse(2, rect); s = polygon_glimpse(3, rect); ax = dlink_new(); ax->object = (void *)polygon_new_and_copy(rect); dlist_insert(ax, circumrects); temp = get_distance_of_p2p(p, q) * get_distance_of_p2p(q, r); if (temp < area) area = temp; } // Update crossing verteces between rectangle and convexhull cross_vertex[irotate] = pivot_next; pivot = NULL; for (i = 0, ax = rect->tail->next; ax != rect->head; ax = ax->next) { delta = (*((real_t *)cross_vertex[i]->spare) - *((real_t *)ax->spare) + 2 * M_PI); if (delta >= 2 * M_PI) delta -= 2 * M_PI; if (pivot == NULL || delta < dmin) { pivot = cross_vertex[i]; dmin = delta; irotate = i; } i++; } p = polygon_glimpse(0, rect); q = polygon_glimpse(1, rect); r = polygon_glimpse(2, rect); s = polygon_glimpse(3, rect); } while (pivot != start); point_destroy(polygon_pop(rect)); point_destroy(polygon_pop(rect)); point_destroy(polygon_pop(rect)); point_destroy(polygon_pop(rect)); polygon_destroy(rect); free(angle); }