Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
0
polygon_t* polygon_clone(polygon_t* poly)
{
  return polygon_new(poly->vertices, poly->num_vertices);
}
Beispiel #4
0
/*
 * 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);
}