Exemple #1
0
static GtsSurface * cartesian_grid_triangulate_holes (CartesianGrid * grid,
						      GtsSurface * s)
{
  GtsVertex * v1, * v2, * v3, * v4;
  GtsEdge * e1, * e2, * e3, * e4, * e5;
  gdouble w, h;
  GtsSurface * box;
  GSList * constraints = NULL, * vertices = NULL, * i;
  gpointer data[2];

  g_return_val_if_fail (grid != NULL, NULL);
  g_return_val_if_fail (s != NULL, NULL);

  /* build enclosing box */
  w = grid->xmax - grid->xmin;
  h = grid->ymax - grid->ymin;
  v1 = gts_vertex_new (s->vertex_class, grid->xmin - w, grid->ymin - h, 0.);
  v2 = gts_vertex_new (s->vertex_class, grid->xmax + w, grid->ymin - h, 0.);
  v3 = gts_vertex_new (s->vertex_class, grid->xmax + w, grid->ymax + h, 0.);
  v4 = gts_vertex_new (s->vertex_class, grid->xmin - w, grid->ymax + h, 0.);

  e1 = gts_edge_new (s->edge_class, v1, v2);
  e2 = gts_edge_new (s->edge_class, v2, v3);
  e3 = gts_edge_new (s->edge_class, v3, v4);
  e4 = gts_edge_new (s->edge_class, v4, v1);
  e5 = gts_edge_new (s->edge_class, v1, v3);

  box = gts_surface_new (GTS_SURFACE_CLASS (GTS_OBJECT (s)->klass), 
			 s->face_class, 
			 s->edge_class, 
			 s->vertex_class);
  gts_surface_add_face (box, gts_face_new (s->face_class, e1, e2, e5));
  gts_surface_add_face (box, gts_face_new (s->face_class, e3, e4, e5));

  /* build vertex and constraint list from the boundaries of the input
     surface s */
  data[0] = s;
  data[1] = &constraints;
  gts_surface_foreach_edge (s, (GtsFunc) build_constraint_list, data);
  vertices = gts_vertices_from_segments (constraints);

  /* triangulate holes */
  i = vertices;
  while (i) {
    g_assert (!gts_delaunay_add_vertex (box, i->data, NULL));
    i = i->next;
  }
  g_slist_free (vertices);

  i = constraints;
  while (i) {
    g_assert (!gts_delaunay_add_constraint (box, i->data));
    i = i->next;
  }

  /* destroy corners of the enclosing box */
  gts_allow_floating_vertices = TRUE;
  gts_object_destroy (GTS_OBJECT (v1));
  gts_object_destroy (GTS_OBJECT (v2));
  gts_object_destroy (GTS_OBJECT (v3));
  gts_object_destroy (GTS_OBJECT (v4));
  gts_allow_floating_vertices = FALSE;

  /* remove parts of the mesh which are not holes */
  i = constraints;
  while (i) {
    edge_mark_as_hole (i->data, box);
    i = i->next;
  }
  g_slist_free (constraints);

  /* remove marked and duplicate faces */
  gts_surface_foreach_face_remove (box, (GtsFunc) face_is_marked, NULL);

  /* box now contains only the triangulated holes. */
  return box;
}
Exemple #2
0
int main (int argc, char * argv[])
{
  GPtrArray * vertices;
  GtsFifo * edges;
  guint i, line;
  GtsTriangle * t;
  GtsVertex * v1, * v2, * v3;
  GtsSurface * surface;
  gboolean keep_hull = TRUE;
  gboolean verbose = FALSE;
  gboolean add_constraints = TRUE;
  gboolean remove_holes = FALSE;
  gboolean check_delaunay = FALSE;
  gboolean conform = FALSE;
  gboolean refine = FALSE;
  gboolean split_constraints = FALSE;
  gboolean randomize = FALSE;
  gboolean remove_duplicates = FALSE;
  gint steiner_max = -1;
  gdouble quality = 0., area = G_MAXDOUBLE;
  int c = 0, status = 0;
  const char * fname = NULL;
  GTimer * timer;

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"duplicates", no_argument, NULL, 'd'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'},
      {"randomize", no_argument, NULL, 'r'},
      {"hull", no_argument, NULL, 'b'},
      {"noconst", no_argument, NULL, 'e'},
      {"holes", no_argument, NULL, 'H'},
      {"split", no_argument, NULL, 'S'},
      {"check", no_argument, NULL, 'c'},
      {"files", required_argument, NULL, 'f'},
      {"conform", no_argument, NULL, 'o'},
      {"steiner", required_argument, NULL, 's'},
      {"quality", required_argument, NULL, 'q'},
      {"area", required_argument, NULL, 'a'}
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvbecf:os:q:a:HSrd",
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvbecf:os:q:a:HSrd"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'd': /* duplicates */
      remove_duplicates = TRUE;
      break;
    case 'b': /* do not keep convex hull */
      keep_hull = FALSE;
      break;
    case 'e': /* do not add constrained edges */
      add_constraints = FALSE;
      break;
    case 'H': /* remove holes */
      remove_holes = TRUE;
      break;
    case 'S': /* split constraints */
      split_constraints = TRUE;
      break;
    case 'r': /* randomize */
      randomize = TRUE;
      break;
    case 'c': /* check Delaunay property */
      check_delaunay = TRUE;
      break;
    case 'f': /* generates files */
      fname = optarg;
      break;      
    case 'v': /* verbose */
      verbose = TRUE;
      break;
    case 'o': /* conform */
      conform = TRUE;
      break;
    case 's': /* steiner */
      steiner_max = atoi (optarg);
      break;
    case 'q': /* quality */
      conform = TRUE;
      refine = TRUE;
      quality = atof (optarg);
      break;
    case 'a': /* area */
      conform = TRUE;
      refine = TRUE;
      area = atof (optarg);
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: delaunay [OPTION] < file.gts\n"
	     "Construct the constrained Delaunay triangulation of the input\n"
	     "\n"
	     "  -b       --hull         do not keep convex hull\n"
	     "  -e       --noconst      do not add constrained edges\n"
	     "  -S       --split        split constraints (experimental)\n"
	     "  -H       --holes        remove holes from the triangulation\n"
	     "  -d       --duplicates   remove duplicate vertices\n"
	     "  -r       --randomize    shuffle input vertex list\n"
	     "  -c       --check        check Delaunay property\n"
	     "  -f FNAME --files=FNAME  generate evolution files\n"
	     "  -o       --conform      generate conforming triangulation\n"
	     "  -s N     --steiner=N    maximum number of Steiner points for\n"
	     "                          conforming triangulation (default is no limit)\n"
	     "  -q Q     --quality=Q    Set the minimum acceptable face quality\n"
	     "  -a A     --area=A       Set the maximum acceptable face area\n"
	     "  -v       --verbose      print statistics about the triangulation\n"
	     "  -h       --help         display this help and exit\n"
	     "\n"
	     "Reports bugs to %s\n",
	     GTS_MAINTAINER);
      return 0; /* success */
      break;
    case '?': /* wrong options */
      fprintf (stderr, "Try `delaunay --help' for more information.\n");
      return 1; /* failure */
    }
  }

  /* read file => two lists: vertices and constraints */

  edges = gts_fifo_new ();
  vertices = g_ptr_array_new ();
  if (add_constraints) /* the edge class is a GtsConstraintClass */
    line = read_list (vertices, edges, 
		      GTS_EDGE_CLASS (gts_constraint_class ()),
		      stdin);
  else /* the edge class is a "normal" edge: GtsEdgeClass */
    line = read_list (vertices, edges, 
		      gts_edge_class (), 
		      stdin);

  if (line > 0) {
    fprintf (stderr, "delaunay: error in input file at line %u\n", line);
    return 1;
  }

  timer = g_timer_new ();
  g_timer_start (timer);

  if (randomize)
    shuffle_array (vertices);

  /* create triangle enclosing all the vertices */
  {
    GSList * list = NULL;
    for (i = 0; i < vertices->len; i++)
      list = g_slist_prepend (list, g_ptr_array_index (vertices, i));
    t = gts_triangle_enclosing (gts_triangle_class (), list, 100.);
    g_slist_free (list);
  }
  gts_triangle_vertices (t, &v1, &v2, &v3);

  /* create surface with one face: the enclosing triangle */
  surface = gts_surface_new (gts_surface_class (),
			     gts_face_class (),
			     gts_edge_class (),
			     gts_vertex_class ());
  gts_surface_add_face (surface, gts_face_new (gts_face_class (),
					       t->e1, t->e2, t->e3));

  /* add vertices */
  for (i = 0; i < vertices->len; i++) {
    GtsVertex * v1 = g_ptr_array_index (vertices, i);
    GtsVertex * v = gts_delaunay_add_vertex (surface, v1, NULL);

    g_assert (v != v1);
    if (v != NULL) {
      if (!remove_duplicates) {
	fprintf (stderr, "delaunay: duplicate vertex (%g,%g) in input file\n",
		 GTS_POINT (v)->x, GTS_POINT (v)->y);
	return 1; /* Failure */
      }
      else
	gts_vertex_replace (v1, v);
    }
    if (fname) {
      static guint nf = 1;
      char s[80];
      FILE * fp;

      g_snprintf (s, 80, "%s.%u", fname, nf++);
      fp = fopen (s, "wt");
      gts_surface_write_oogl (surface, fp);
      fclose (fp);

      if (check_delaunay && gts_delaunay_check (surface)) {
	fprintf (stderr, "delaunay: triangulation is not Delaunay\n");
	return 1;
      }
    }
  }
  g_ptr_array_free (vertices, TRUE);

  /* add remaining constraints */
  if (add_constraints)
    gts_fifo_foreach (edges, (GtsFunc) add_constraint, surface);

  /* destroy enclosing triangle */
  gts_allow_floating_vertices = TRUE;
  gts_object_destroy (GTS_OBJECT (v1));
  gts_object_destroy (GTS_OBJECT (v2));
  gts_object_destroy (GTS_OBJECT (v3));
  gts_allow_floating_vertices = FALSE;

  if (!keep_hull)
    gts_delaunay_remove_hull (surface);

  if (remove_holes)
    delaunay_remove_holes (surface);

  if (split_constraints) {
    gpointer data[2];

    data[0] = surface;
    data[1] = edges;
    gts_fifo_foreach (edges, (GtsFunc) split_constraint, data);
  }

  if (conform) {
    guint encroached_number = 
      gts_delaunay_conform (surface, 
			    steiner_max,
			    (GtsEncroachFunc) gts_vertex_encroaches_edge,
			    NULL);
    if (encroached_number == 0 && refine) {
      guint unrefined_number;
      gpointer data[2];
      
      data[0] = &quality;
      data[1] = &area;
      unrefined_number = 
	gts_delaunay_refine (surface, 
			     steiner_max,
			     (GtsEncroachFunc) gts_vertex_encroaches_edge,
			     NULL,
			     (GtsKeyFunc) triangle_cost,
			     data);
      if (verbose && unrefined_number > 0)
	fprintf (stderr, 
		 "delaunay: ran out of Steiner points (max: %d) during refinement\n"
		 "%d unrefined faces left\n",
		 steiner_max, unrefined_number);
    }
    else if (verbose && encroached_number > 0)
      fprintf (stderr, 
	       "delaunay: ran out of Steiner points (max: %d) during conforming\n"
	       "Delaunay triangulation: %d encroached constraints left\n",
	       steiner_max, encroached_number);
  }
  g_timer_stop (timer);

  if (verbose) {
    gts_surface_print_stats (surface, stderr);
    fprintf (stderr, "# Triangulation time: %g s speed: %.0f vertex/s\n", 
	  g_timer_elapsed (timer, NULL),
	  gts_surface_vertex_number (surface)/g_timer_elapsed (timer, NULL));
  }

  if (check_delaunay && gts_delaunay_check (surface)) {
    fprintf (stderr, "delaunay: triangulation is not Delaunay\n");
    status = 1; /* failure */
  }

  /* write triangulation */
  gts_surface_write (surface, stdout);

  return status;
}
Exemple #3
0
int main (int argc, char * argv[])
{
  guint i, j, nx, ny;
  gdouble cosa, sina;
  GtsSurface * surface;
  GSList * l, * vertices = NULL;
  GtsTriangle * t;
  GtsVertex * v1, * v2, * v3;
  GTimer * timer;

  if (argc != 4) {
    fprintf (stderr, "usage: cartesian nx ny angle\n");
    return 0;
  }

  nx = strtol (argv[1], NULL, 0);
  ny = strtol (argv[2], NULL, 0);
  cosa = cos (strtod (argv[3], NULL));
  sina = sin (strtod (argv[3], NULL));

  timer = g_timer_new ();
  g_timer_start (timer);
  for (i = 0; i < nx; i++) {
    gdouble x = (gdouble) i/(gdouble) (nx - 1); 
    for (j = 0; j < ny; j++) {
      gdouble y = (gdouble) j/(gdouble) (nx - 1); 
      vertices = g_slist_prepend (vertices, 
		     gts_vertex_new (gts_vertex_class (),
				     cosa*x - sina*y, sina*x + cosa*y, 0.));
    }
  }

  t = gts_triangle_enclosing (gts_triangle_class (), vertices, 100.);
  gts_triangle_vertices (t, &v1, &v2, &v3);
  surface = gts_surface_new (gts_surface_class (),
			     gts_face_class (),
			     gts_edge_class (),
			     gts_vertex_class ());
  gts_surface_add_face (surface, gts_face_new (gts_face_class (),
					       t->e1, t->e2, t->e3));
  g_timer_stop (timer);
  fprintf (stderr, "Input: %g s\n", g_timer_elapsed (timer, NULL));
  g_timer_reset (timer);

  g_timer_start (timer);
  l = vertices;
  while (l) {
    g_assert (gts_delaunay_add_vertex (surface, l->data, NULL) == NULL);
    l = l->next;
  }

  gts_allow_floating_vertices = TRUE;
  gts_object_destroy (GTS_OBJECT (v1));
  gts_object_destroy (GTS_OBJECT (v2));
  gts_object_destroy (GTS_OBJECT (v3));
  gts_allow_floating_vertices = FALSE;
  g_timer_stop (timer);

  fprintf (stderr, "Triangulation: %g s speed: %.0f vertex/s\n", 
	   g_timer_elapsed (timer, NULL),
	   g_slist_length (vertices)/g_timer_elapsed (timer, NULL));
  g_timer_reset (timer);

  g_timer_start (timer);
  gts_surface_write (surface, stdout);
  g_timer_stop (timer);

  fprintf (stderr, "Output: %g s\n", g_timer_elapsed (timer, NULL));

  if (gts_delaunay_check (surface)) {
    fprintf (stderr, "WARNING: surface is not Delaunay\n");
    return 0;
  }

  return 1;
}
Exemple #4
0
/* tri:
 * Main entry point to using GTS for triangulation.
 * Input is npt points with x and y coordinates stored either separately
 * in x[] and y[] (sepArr != 0) or consecutively in x[] (sepArr == 0).
 * Optionally, the input can include nsegs line segments, whose endpoint
 * indices are supplied in segs[2*i] and segs[2*i+1] yielding a constrained
 * triangulation.
 *
 * The return value is the corresponding gts surface, which can be queries for
 * the triangles and line segments composing the triangulation.
 */
static GtsSurface*
tri(double *x, double *y, int npt, int *segs, int nsegs, int sepArr)
{
    int i;
    GtsSurface *surface;
    GVertex **vertices = N_GNEW(npt, GVertex *);
    GtsEdge **edges = N_GNEW(nsegs, GtsEdge*);
    GSList *list = NULL;
    GtsVertex *v1, *v2, *v3;
    GtsTriangle *t;
    GtsVertexClass *vcl = (GtsVertexClass *) g_vertex_class();
    GtsEdgeClass *ecl = GTS_EDGE_CLASS (gts_constraint_class ());

    if (sepArr) {
	for (i = 0; i < npt; i++) {
	    GVertex *p = (GVertex *) gts_vertex_new(vcl, x[i], y[i], 0);
	    p->idx = i;
	    vertices[i] = p;
	}
    }
    else {
	for (i = 0; i < npt; i++) {
	    GVertex *p = (GVertex *) gts_vertex_new(vcl, x[2*i], x[2*i+1], 0);
	    p->idx = i;
	    vertices[i] = p;
	}
    }

    /* N.B. Edges need to be created here, presumably before the
     * the vertices are added to the face. In particular, they cannot
     * be added created and added vi gts_delaunay_add_constraint() below.
     */
    for (i = 0; i < nsegs; i++) {
	edges[i] = gts_edge_new(ecl,
		 (GtsVertex *) (vertices[ segs[ 2 * i]]),
		 (GtsVertex *) (vertices[ segs[ 2 * i + 1]]));
    }

    for (i = 0; i < npt; i++)
	list = g_slist_prepend(list, vertices[i]);
    t = gts_triangle_enclosing(gts_triangle_class(), list, 100.);
    g_slist_free(list);

    gts_triangle_vertices(t, &v1, &v2, &v3);

    surface = gts_surface_new(gts_surface_class(),
				  (GtsFaceClass *) g_face_class(),
				  gts_edge_class(),
				  gts_vertex_class());
    gts_surface_add_face(surface, gts_face_new(gts_face_class(),
					       t->e1, t->e2, t->e3));

    for (i = 0; i < npt; i++) {
	GtsVertex *v1 = (GtsVertex *) vertices[i];
	GtsVertex *v = gts_delaunay_add_vertex(surface, v1, NULL);

	/* if v != NULL, it is a previously added pt with the same
	 * coordinates as v1, in which case we replace v1 with v
	 */
	if (v) {
	    /* agerr (AGWARN, "Duplicate point %d %d\n", i, ((GVertex*)v)->idx); */
	    gts_vertex_replace (v1, v);
	}
    }

    for (i = 0; i < nsegs; i++) {
	gts_delaunay_add_constraint(surface,GTS_CONSTRAINT(edges[i]));
    }

    /* destroy enclosing triangle */
    gts_allow_floating_vertices = TRUE;
    gts_allow_floating_edges = TRUE;
/*
    gts_object_destroy(GTS_OBJECT(v1));
    gts_object_destroy(GTS_OBJECT(v2));
    gts_object_destroy(GTS_OBJECT(v3));
*/
    destroy(v1);
    destroy(v2);
    destroy(v3);
    gts_allow_floating_edges = FALSE;
    gts_allow_floating_vertices = FALSE;

    if (nsegs)
	delaunay_remove_holes(surface);

    free (edges);
    free(vertices);
    return surface;
}