Example #1
0
void gts_triangulate_convex_polygon_test()
{
	int i; 
	gdouble v[5][3] = {
		{0.0, 0.0, 1.0},
		{0.0, 2.0, 2.0},
		{2.0, 3.0, 1.0},
		{4.0, 1.0, 1.0},
		{2.0, 0.0, 0.0}
	};
	
	GtsEdgePool *pool = gts_edge_pool_new(gts_edge_pool_class());
	GtsVertex *vtx[5]; 
	GCList *polygon = NULL;
	GCList *wired = NULL; 
	GtsSurfaceStats sstats; 
	
	for (i = 0; i < 5; ++i) {
		vtx[i] = gts_vertex_new(gts_vertex_class(), v[i][0],v[i][1],v[i][2]); 
		polygon = g_clist_append(polygon, vtx[i]);
	}
	polygon = g_clist_append(polygon, vtx[0]);
	polygon = g_clist_append(polygon, vtx[1]);
	
	wired = g_clist_append(wired, vtx[0]);
	wired = g_clist_append(wired, vtx[1]);
	wired = g_clist_append(wired, vtx[0]);
	wired = g_clist_append(wired, vtx[2]);
	
	
		
	GtsSurface *s = gts_surface_new(gts_surface_class(), 
					gts_face_class(), 
					gts_edge_class(),
					gts_vertex_class());
	
	gts_triangulate_convex_polygon(s, pool, wired);
	g_assert(gts_surface_face_number(s) == 0);

	gts_triangulate_convex_polygon(s, pool, polygon);  

	g_message("gts_surface_face_number = %d", gts_surface_face_number(s));  
	g_assert(gts_surface_face_number(s) == 3);
	gts_surface_stats(s, &sstats);
	
	g_assert(sstats.n_incompatible_faces == 0); 
	g_assert(sstats.n_duplicate_faces == 0);	
	g_assert(sstats.n_duplicate_edges == 0);	
	g_assert(sstats.n_boundary_edges == 5);	
	g_assert(sstats.n_non_manifold_edges == 0);	
	g_assert(sstats.faces_per_edge.min == 1); 
	g_assert(sstats.faces_per_edge.max == 2);	
	
	g_message("Triangulate convex polygon PASS"); 

	gts_object_destroy(GTS_OBJECT(pool)); 
}
Example #2
0
File: oocs.c Project: Gilles86/afni
int main (int argc, char * argv[])
{
  GtsSurface * s;
  GtsBBox * bbox;
  gdouble delta;
  GtsPoint * p1, * p2, * p3;
  guint nt;
  GtsRange cluster_stats;
  GtsClusterGrid * cluster_grid;
  
  if (argc != 2) {
    fprintf (stderr, "usage: oocs DELTA < infile > outfile\n");
    return 1;
  }

  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());

  bbox = gts_bbox_new (gts_bbox_class (), s, 0., 0., 0., 0., 0., 0.);
  scanf ("%u", &nt);
  scanf ("%lf %lf %lf", &bbox->x1, &bbox->y1, &bbox->z1);
  scanf ("%lf %lf %lf", &bbox->x2, &bbox->y2, &bbox->z2);
  delta = atof (argv[1])*sqrt (gts_bbox_diagonal2 (bbox));

  cluster_grid = gts_cluster_grid_new (gts_cluster_grid_class (), 
				       gts_cluster_class (), 
				       s, bbox, delta);

  p1 = gts_point_new (gts_point_class (), 0., 0., 0.);
  p2 = gts_point_new (gts_point_class (), 0., 0., 0.);
  p3 = gts_point_new (gts_point_class (), 0., 0., 0.);

  while (scanf ("%lf %lf %lf", &p1->x, &p1->y, &p1->z) == 3 &&
	 scanf ("%lf %lf %lf", &p2->x, &p2->y, &p2->z) == 3 &&
	 scanf ("%lf %lf %lf", &p3->x, &p3->y, &p3->z) == 3)
    gts_cluster_grid_add_triangle (cluster_grid, p1, p2, p3, NULL);
  cluster_stats = gts_cluster_grid_update (cluster_grid);

  gts_object_destroy (GTS_OBJECT (p1));
  gts_object_destroy (GTS_OBJECT (p2));
  gts_object_destroy (GTS_OBJECT (p3));
  gts_object_destroy (GTS_OBJECT (cluster_grid));

  fprintf (stderr, "Initial number of triangles: %u\n", nt);
  fprintf (stderr, "%d clusters of size: min: %g avg: %.1f|%.1f max: %g\n",
	   cluster_stats.n,
	   cluster_stats.min, 
	   cluster_stats.mean, cluster_stats.stddev, 
	   cluster_stats.max);
  gts_surface_print_stats (s, stderr);
  gts_surface_write (s, stdout);

  return 0;
}
Example #3
0
    void add_triangle(k3d::uint_t Vertices[3], k3d::uint_t Edges[3])
    {
        GtsVertex* const vertex1 = get_vertex(Vertices[0]);
        GtsVertex* const vertex2 = get_vertex(Vertices[1]);
        GtsVertex* const vertex3 = get_vertex(Vertices[2]);

        GtsEdge* const edge1 = gts_edge_new(gts_edge_class(), vertex1, vertex2);
        GtsEdge* const edge2 = gts_edge_new(gts_edge_class(), vertex2, vertex3);
        GtsEdge* const edge3 = gts_edge_new(gts_edge_class(), vertex3, vertex1);

        GtsFace* const face = gts_face_new(gts_face_class(), edge1, edge2, edge3);

        gts_surface_add_face(gts_surface, face);
    }
Example #4
0
    GtsSurface* process(const k3d::mesh& Mesh, const k3d::polyhedron::const_primitive& Polyhedron)
    {
        gts_surface = gts_surface_new(gts_surface_class(), gts_face_class(), gts_edge_class(), gts_vertex_class());

        mesh_points = Mesh.points.get();
        gts_vertices.assign(mesh_points->size(), 0);

        base::process(Mesh, Polyhedron);

        gts_vertices.clear();
        mesh_points = 0;

        return gts_surface;
    }
Example #5
0
static GtsObject *
parent(GtsFace *face) {
  GtsSurface *p;

  p = gts_surface_new(gts_surface_class(), gts_face_class(),
		      gts_edge_class(), gts_vertex_class());

  if( p == NULL )  {
    PyErr_SetString(PyExc_MemoryError, "could not create parent");
    return NULL;
  }
  gts_surface_add_face(p,face);

  return GTS_OBJECT(p);
}
Example #6
0
static GFaceClass *g_face_class(void)
{
    static GFaceClass *klass = NULL;

    if (klass == NULL) {
	GtsObjectClassInfo face_info = {
	    "GFace",
	    sizeof(GFace),
	    sizeof(GFaceClass),
	    (GtsObjectClassInitFunc) NULL,
	    (GtsObjectInitFunc) NULL,
	    (GtsArgSetFunc) NULL,
	    (GtsArgGetFunc) NULL
	};
	klass = gts_object_class_new(GTS_OBJECT_CLASS(gts_face_class()),
				     &face_info);
    }

    return klass;
}
Example #7
0
int main (int argc, char * argv[])
{
  GtsSurface * s;
  guint i;
  GtsFile * fp;
  guint nv = 1, ne = 1, nf = 1;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());
  fp = gts_file_new (stdin);
  if (gts_surface_read (s, fp)) {
    fputs ("gtstoc: file on standard input is not a valid GTS file\n", 
	   stderr);
    fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
    return 1; /* failure */
  }

  printf ("  GtsSurface * surface = gts_surface_new (gts_surface_class (),\n"
	  "                                          gts_face_class (),\n"
	  "                                          gts_edge_class (),\n"
	  "                                          gts_vertex_class ());\n\n");
  gts_surface_foreach_vertex (s, (GtsFunc) write_vertex, &nv);
  printf ("\n");
  gts_surface_foreach_edge (s, (GtsFunc) write_edge, &ne);  
  printf ("\n");
  gts_surface_foreach_face (s, (GtsFunc) write_face, &nf);  
  printf ("  \n");
  for (i = 1; i < nf; i++)
    printf ("  gts_surface_add_face (surface, f%u);\n", i);

  return 0;
}
Example #8
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;
}
Example #9
0
int main (int argc, char * argv[])
{
  GtsSurface * s;
  GtsFile * fp;
  int c = 0;
  gboolean verbose = FALSE;
  guint n, niter;
  gdouble lambda;
  gpointer data[4];
  gboolean fold = FALSE;
  gdouble maxcosine2 = 0.;
  guint nfold = 1;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"fold", required_argument, NULL, 'f'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'}
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvf:", 
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvf:"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'f': /* fold */
      fold = TRUE;
      maxcosine2 = cos (atof (optarg)*3.14159265359/180.);
      maxcosine2 *= maxcosine2;
      break;
    case 'v': /* verbose */
      verbose = TRUE;
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: smooth [OPTION] LAMBDA NITER < file.gts > smooth.gts\n"
	     "Smooth a GTS file by applying NITER iterations of a Laplacian filter\n"
	     "of parameter LAMBDA.\n"
	     "\n"
	     "  -f VAL  --fold=VAL   smooth only folds\n"
	     "  -v      --verbose    print statistics about the surface\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 `smooth --help' for more information.\n");
      return 1; /* failure */
    }
  }

  if (optind >= argc) { /* missing lambda */
    fprintf (stderr, 
	     "smooth: missing LAMBDA\n"
	     "Try `smooth --help' for more information.\n");
    return 1; /* failure */
  }
  lambda = atof (argv[optind++]);

  if (optind >= argc) { /* missing niter */
    fprintf (stderr, 
	     "smooth: missing NITER\n"
	     "Try `smooth --help' for more information.\n");
    return 1; /* failure */
  }
  niter = atoi (argv[optind++]);

  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());
  fp = gts_file_new (stdin);
  if (gts_surface_read (s, fp)) {
    fputs ("smooth: file on standard input is not a valid GTS file\n", 
	   stderr);
    fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
    return 1; /* failure */
  }

  if (verbose)
    gts_surface_print_stats (s, stderr);

  data[0] = s;
  data[1] = &lambda;
  data[2] = &maxcosine2;
  data[3] = &nfold;

  for (n = 1; n <= niter && (!fold || nfold > 0); n++) {
    if (fold) {
      nfold = 0;
      gts_surface_foreach_vertex (s, (GtsFunc) smooth_fold, data);
    }
    else
      gts_surface_foreach_vertex (s, (GtsFunc) smooth_vertex, data);
    if (verbose)
      fprintf (stderr, "\rIteration: %10u %3.0f%% ",
	       n,
	       100.*n/niter);
  }

  if (verbose) {
    fputc ('\n', stderr);
    gts_surface_print_stats (s, stderr);
  }

  gts_surface_write (s, stdout);

  return 0;
}
Example #10
0
GSList *gts_vertex_faces( GtsVertex *v, GtsSurface *surface, GSList *list )
{
  int eax;
  GSList *i;
{
  /* phantom */ int _g_boolean_var_;
  if ( v == 0 )
  {
    g_return_if_fail_warning( 0, __PRETTY_FUNCTION__, "v != NULL" );
    list = 0;
  }
  i = &v->segments;
  if ( v->segments[4].next )
  {
  {
    do
    {
      if ( gts_edge_class( ) == 0 )
      {
        g_return_if_fail_warning( 0, __PRETTY_FUNCTION__, "klass != NULL" );
        i = &i->next;
        if ( i->next == 0 )
          break;
      }
      else
      {
        if ( i->data[0] )
        {
          if ( *(int*)(i->data[0]) == 0 )
          {
            g_return_if_fail_warning( 0, __PRETTY_FUNCTION__, "c != NULL" );
            i = &i->next;
            if ( i->next == 0 )
              break;
          }
          else
          do
          {
            if ( *(int*)(*(int*)(i->data[0]) + 64) == gts_edge_class( ) )
            {
              GSList *j = j[2].next;
              if ( j[2].next )
              {
              {
                do
                {
                  if ( gts_face_class( ) == 0 )
                    g_return_if_fail_warning( 0, __PRETTY_FUNCTION__, "klass != NULL" );
                  else
                  if ( j )
                  {
                    if ( j->data[0] == 0 )
                      g_return_if_fail_warning( 0, __PRETTY_FUNCTION__, "c != NULL" );
                    else
                    do
                    {
                      if ( j->_GSList == gts_face_class( ) )
                      {
                        if ( ( !surface || gts_face_has_parent_surface( &j->data[0], surface ) ) && g_slist_find( list, &j ) == 0 )
                        {
                          list = g_slist_prepend( list, &j );
                          break;
                        }
                        else
                          break;
                      }
                      else
                    }
                    while ( j->_GSList );
                  }
                  j = j->next;
                }
                while ( j->next );
                break;
              }
              }
              else
                break;
            }
            else
            {
            }
          }
          while ( *(int*)(*(int*)(*(int*)(i->data[0]) + 64) + 64) );
        }
        i = &i->next;
      }
    }
Example #11
0
int main (int argc, char * argv[])
{
  GtsSurface * s;
  GtsFile * fp;
  GtsMatrix * m;
  int c = 0;
  gboolean verbose = FALSE;
  gboolean revert = FALSE;
  gboolean normalize = FALSE;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  m = gts_matrix_identity (NULL);

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"rx", required_argument, NULL, 'r'},
      {"ry", required_argument, NULL, 'm'},
      {"rz", required_argument, NULL, 'n'},
      {"scale", required_argument, NULL, 's'},
      {"sx", required_argument, NULL, 'R'},
      {"sy", required_argument, NULL, 'M'},
      {"sz", required_argument, NULL, 'N'},
      {"tx", required_argument, NULL, 't'},
      {"ty", required_argument, NULL, 'u'},
      {"tz", required_argument, NULL, 'w'},
      {"revert", no_argument, NULL, 'i'},
      {"normalize", no_argument, NULL, 'o'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'},
      { NULL }
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvr:m:n:s:R:M:N:it:u:w:o",
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvr:m:n:s:R:M:N:it:u:w:o"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'o': /* normalize */
      normalize = TRUE;
      break;
    case 'r': { /* rotate around x-axis */
      gdouble angle, cosa, sina;
      GtsMatrix * rot, * p;
      
      rot = gts_matrix_identity (NULL);
      angle = atof (optarg)*PI/180.;
      cosa = cos (angle);
      sina = sin (angle);
      rot[1][1] = cosa; rot[1][2] = -sina;
      rot[2][1] = sina; rot[2][2] = cosa;
      p = gts_matrix_product (m, rot);
      gts_matrix_destroy (rot);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 'm': { /* rotate around y-axis */
      gdouble angle, cosa, sina;
      GtsMatrix * rot, * p;
      
      rot = gts_matrix_identity (NULL);
      angle = atof (optarg)*PI/180.;
      cosa = cos (angle);
      sina = sin (angle);
      rot[0][0] = cosa; rot[0][2] = sina;
      rot[2][0] = -sina; rot[2][2] = cosa;
      p = gts_matrix_product (m, rot);
      gts_matrix_destroy (rot);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 'n': { /* rotate around z-axis */
      gdouble angle, cosa, sina;
      GtsMatrix * rot, * p;
      
      rot = gts_matrix_identity (NULL);
      angle = atof (optarg)*PI/180.;
      cosa = cos (angle);
      sina = sin (angle);
      rot[0][0] = cosa; rot[0][1] = -sina;
      rot[1][0] = sina; rot[1][1] = cosa;
      p = gts_matrix_product (m, rot);
      gts_matrix_destroy (rot);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 's': { /* scale */
      GtsMatrix * scale, * p;
      gdouble s = atof (optarg);

      scale = gts_matrix_identity (NULL);
      scale[0][0] = scale[1][1] = scale[2][2] = s;
      p = gts_matrix_product (m, scale);
      gts_matrix_destroy (scale);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 'R': { /* sx */
      GtsMatrix * scale, * p;
      gdouble s = atof (optarg);

      scale = gts_matrix_identity (NULL);
      scale[0][0] = s;
      p = gts_matrix_product (m, scale);
      gts_matrix_destroy (scale);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 'M': { /* sy */
      GtsMatrix * scale, * p;
      gdouble s = atof (optarg);

      scale = gts_matrix_identity (NULL);
      scale[1][1] = s;
      p = gts_matrix_product (m, scale);
      gts_matrix_destroy (scale);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 'N': { /* sz */
      GtsMatrix * scale, * p;
      gdouble s = atof (optarg);

      scale = gts_matrix_identity (NULL);
      scale[2][2] = s;
      p = gts_matrix_product (m, scale);
      gts_matrix_destroy (scale);
      gts_matrix_destroy (m);
      m = p;
      break;
    }
    case 't': /* tx */
      m[0][3] += atof (optarg);
      break;
    case 'u': /* ty */
      m[1][3] += atof (optarg);
      break;
    case 'w': /* tz */
      m[2][3] += atof (optarg);
      break;
    case 'i': /* revert */
      revert = TRUE;
      break;
    case 'v': /* verbose */
      verbose = TRUE;
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: transform [OPTION] < file.gts\n"
	     "Apply geometric transformations to the input.\n"
	     "\n"
	     "  -r ANGLE  --rx=ANGLE      rotate around x-axis (angle in degrees)\n"
	     "  -m ANGLE  --ry=ANGLE      rotate around y-axis\n"
	     "  -n ANGLE  --rz=ANGLE      rotate around z-axis\n"
	     "  -s FACTOR --scale=FACTOR  scale by FACTOR\n"
	     "  -R FACTOR --sx=FACTOR     scale x-axis by FACTOR\n"
	     "  -M FACTOR --sy=FACTOR     scale y-axis by FACTOR\n"
	     "  -N FACTOR --sz=FACTOR     scale z-axis by FACTOR\n"
             "  -t V      --tx=V          translate of V along x-axis\n"
             "  -u V      --ty=V          translate of V along y-axis\n"
             "  -w V      --tz=V          translate of V along z-axis\n"
	     "  -i        --revert        turn surface inside out\n"
             "  -o        --normalize     fit the resulting surface in a cube of\n"
	     "                            size 1 centered at the origin\n"
	     "  -v        --verbose       print statistics about the surface\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 `transform --help' for more information.\n");
      return 1; /* failure */
    }
  }

  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());
  fp = gts_file_new (stdin);
  if (gts_surface_read (s, fp)) {
    fputs ("transform: file on standard input is not a valid GTS file\n", 
	   stderr);
    fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
    return 1; /* failure */
  }

  if (verbose)
    gts_surface_print_stats (s, stderr);

  if (revert)
    gts_surface_foreach_face (s, (GtsFunc) gts_triangle_revert, NULL);
  gts_surface_foreach_vertex (s, (GtsFunc) gts_point_transform, m);
  if (normalize) {
    GtsBBox * bb = gts_bbox_surface (gts_bbox_class (), s);
    gdouble scale = bb->x2 - bb->x1;
    GtsMatrix * sc;

    if (bb->y2 - bb->y1 > scale) scale = bb->y2 - bb->y1;
    if (bb->z2 - bb->z1 > scale) scale = bb->z2 - bb->z1;
    if (scale > 0.) scale = 1./scale;
    else scale = 1.;
    sc = gts_matrix_identity (NULL);
    sc[0][3] = - (bb->x1 + bb->x2)/2.;
    sc[1][3] = - (bb->y1 + bb->y2)/2.;
    sc[2][3] = - (bb->z1 + bb->z2)/2.;
    gts_surface_foreach_vertex (s, (GtsFunc) gts_point_transform, sc);
    sc[0][0] = sc[1][1] = sc[2][2] = scale;    
    sc[0][3] = sc[1][3] = sc[2][3] = 0.;
    gts_surface_foreach_vertex (s, (GtsFunc) gts_point_transform, sc);
    gts_matrix_destroy (sc);
  }
  gts_surface_write (s, stdout);

  return 0;
}
Example #12
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;
}
Example #13
0
int main (int argc, char * argv[])
{
  GtsSurface * surface = gts_surface_new (gts_surface_class (),
                                          gts_face_class (),
                                          gts_edge_class (),
                                          gts_vertex_class ());

  GtsVertex * v1 = gts_vertex_new (gts_vertex_class (), 0, 0, 0);
  GtsVertex * v2 = gts_vertex_new (gts_vertex_class (), 0, -0.5, 1);
  GtsVertex * v3 = gts_vertex_new (gts_vertex_class (), 0, 0.5, 1);
  GtsVertex * v4 = gts_vertex_new (gts_vertex_class (), 1, 0, 0);
  GtsVertex * v5 = gts_vertex_new (gts_vertex_class (), 0, -0.5, -1);
  GtsVertex * v6 = gts_vertex_new (gts_vertex_class (), 1, -0.5, -1);
  GtsVertex * v7 = gts_vertex_new (gts_vertex_class (), 1, 0.5, -1);
  GtsVertex * v8 = gts_vertex_new (gts_vertex_class (), 1, -0.5, 1);
  GtsVertex * v9 = gts_vertex_new (gts_vertex_class (), 1, 0.5, 1);
  GtsVertex * v10 = gts_vertex_new (gts_vertex_class (), 0, 0.5, -1);

  GtsEdge * e1 = gts_edge_new (gts_edge_class (), v1, v2);
  GtsEdge * e2 = gts_edge_new (gts_edge_class (), v1, v3);
  GtsEdge * e3 = gts_edge_new (gts_edge_class (), v2, v3);
  GtsEdge * e4 = gts_edge_new (gts_edge_class (), v4, v5);
  GtsEdge * e5 = gts_edge_new (gts_edge_class (), v4, v6);
  GtsEdge * e6 = gts_edge_new (gts_edge_class (), v5, v6);
  GtsEdge * e7 = gts_edge_new (gts_edge_class (), v1, v4);
  GtsEdge * e8 = gts_edge_new (gts_edge_class (), v1, v5);
  GtsEdge * e9 = gts_edge_new (gts_edge_class (), v6, v7);
  GtsEdge * e10 = gts_edge_new (gts_edge_class (), v4, v7);
  GtsEdge * e11 = gts_edge_new (gts_edge_class (), v1, v7);
  GtsEdge * e12 = gts_edge_new (gts_edge_class (), v8, v9);
  GtsEdge * e13 = gts_edge_new (gts_edge_class (), v4, v9);
  GtsEdge * e14 = gts_edge_new (gts_edge_class (), v4, v8);
  GtsEdge * e15 = gts_edge_new (gts_edge_class (), v5, v10);
  GtsEdge * e16 = gts_edge_new (gts_edge_class (), v1, v10);
  GtsEdge * e17 = gts_edge_new (gts_edge_class (), v10, v7);
  GtsEdge * e18 = gts_edge_new (gts_edge_class (), v1, v8);
  GtsEdge * e19 = gts_edge_new (gts_edge_class (), v2, v8);
  GtsEdge * e20 = gts_edge_new (gts_edge_class (), v4, v3);
  GtsEdge * e21 = gts_edge_new (gts_edge_class (), v3, v9);

  GtsFace * f1 = gts_face_new (gts_face_class (),
                                e1, e2, e3);
  GtsFace * f2 = gts_face_new (gts_face_class (),
                                e4, e5, e6);
  GtsFace * f3 = gts_face_new (gts_face_class (),
                                e7, e4, e8);
  GtsFace * f4 = gts_face_new (gts_face_class (),
                                e9, e5, e10);
  GtsFace * f5 = gts_face_new (gts_face_class (),
                                e11, e10, e7);
  GtsFace * f6 = gts_face_new (gts_face_class (),
                                e12, e13, e14);
  GtsFace * f7 = gts_face_new (gts_face_class (),
                                e15, e16, e8);
  GtsFace * f8 = gts_face_new (gts_face_class (),
                                e17, e11, e16);
  GtsFace * f9 = gts_face_new (gts_face_class (),
                                e18, e14, e7);
  GtsFace * f10 = gts_face_new (gts_face_class (),
                                e19, e18, e1);
  GtsFace * f11 = gts_face_new (gts_face_class (),
                                e20, e13, e21);
  GtsFace * f12 = gts_face_new (gts_face_class (),
                                e7, e20, e2);
  GtsVertex * v;
  GtsVolumeOptimizedParams params = { 0.5, 0.5, 0.0 };
  GtsSplit * vs;

  gts_surface_add_face (surface, f1);
  gts_surface_add_face (surface, f2);
  gts_surface_add_face (surface, f3);
  gts_surface_add_face (surface, f4);
  gts_surface_add_face (surface, f5);
  gts_surface_add_face (surface, f6);
  gts_surface_add_face (surface, f7);
  gts_surface_add_face (surface, f8);
  gts_surface_add_face (surface, f9);
  gts_surface_add_face (surface, f10);
  gts_surface_add_face (surface, f11);
  gts_surface_add_face (surface, f12);

  g_assert (gts_edge_collapse_is_valid (e7));
  v = gts_volume_optimized_vertex (e7, gts_vertex_class (), &params);
  vs = gts_split_new (gts_split_class (), v, 
		      GTS_OBJECT (GTS_SEGMENT (e7)->v1),
		      GTS_OBJECT (GTS_SEGMENT (e7)->v2));
  gts_split_collapse (vs, gts_edge_class (), NULL);

  gts_surface_write (surface, stdout);

  return 0;
}
Example #14
0
/* set - compute set operations between surfaces */
int main (int argc, char * argv[])
{
  GtsSurface * s1, * s2, * s3;
  GtsSurfaceInter * si;
  GNode * tree1, * tree2;
  FILE * fptr;
  GtsFile * fp;
  int c = 0;
  gboolean verbose = TRUE;
  gboolean inter = FALSE;
  gboolean check_self_intersection = FALSE;
  gchar * operation, * file1, * file2;
  gboolean closed = TRUE, is_open1, is_open2;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"inter", no_argument, NULL, 'i'},
      {"self", no_argument, NULL, 's'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'}
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvis", 
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvis"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 's': /* self */
      check_self_intersection = TRUE;
      break;
    case 'i': /* inter */
      inter = TRUE;
      break;
    case 'v': /* verbose */
      verbose = FALSE;
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: set [OPTION] OPERATION FILE1 FILE2\n"
             "Compute set operations between surfaces, where OPERATION is either.\n"
             "union, inter, diff.\n"
	     "\n"
             "  -i      --inter    output an OOGL (Geomview) representation of the curve\n"
             "                     intersection of the surfaces\n"
	     "  -s      --self     checks that the surfaces are not self-intersecting\n"
             "                     if one of them is, the set of self-intersecting faces\n"
	     "                     is written (as a GtsSurface) on standard output\n"
	     "  -v      --verbose  do not print statistics about the surface\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 `set --help' for more information.\n");
      return 1; /* failure */
    }
  }

  if (optind >= argc) { /* missing OPERATION */
    fprintf (stderr, 
	     "set: missing OPERATION\n"
	     "Try `set --help' for more information.\n");
    return 1; /* failure */
  }
  operation = argv[optind++];

  if (optind >= argc) { /* missing FILE1 */
    fprintf (stderr, 
	     "set: missing FILE1\n"
	     "Try `set --help' for more information.\n");
    return 1; /* failure */
  }
  file1 = argv[optind++];

  if (optind >= argc) { /* missing FILE2 */
    fprintf (stderr, 
	     "set: missing FILE2\n"
	     "Try `set --help' for more information.\n");
    return 1; /* failure */
  }
  file2 = argv[optind++];

  /* open first file */
  if ((fptr = fopen (file1, "rt")) == NULL) {
    fprintf (stderr, "set: can not open file `%s'\n", file1);
    return 1;
  }
  /* reads in first surface file */
  s1 = GTS_SURFACE (gts_object_new (GTS_OBJECT_CLASS (gts_surface_class ())));
  fp = gts_file_new (fptr);
  if (gts_surface_read (s1, fp)) {
    fprintf (stderr, "set: `%s' is not a valid GTS surface file\n", 
	     file1);
    fprintf (stderr, "%s:%d:%d: %s\n", file1, fp->line, fp->pos, fp->error);
    return 1;
  }
  gts_file_destroy (fp);
  fclose (fptr);

  /* open second file */
  if ((fptr = fopen (file2, "rt")) == NULL) {
    fprintf (stderr, "set: can not open file `%s'\n", file2);
    return 1;
  }
  /* reads in second surface file */
  s2 = GTS_SURFACE (gts_object_new (GTS_OBJECT_CLASS (gts_surface_class ())));
  fp = gts_file_new (fptr);
  if (gts_surface_read (s2, fp)) {
    fprintf (stderr, "set: `%s' is not a valid GTS surface file\n", 
	     file2);
    fprintf (stderr, "%s:%d:%d: %s\n", file2, fp->line, fp->pos, fp->error);
    return 1;
  }
  gts_file_destroy (fp);
  fclose (fptr);

  /* display summary information about both surfaces */
  if (verbose) {
    gts_surface_print_stats (s1, stderr);
    gts_surface_print_stats (s2, stderr);
  }

  /* check that the surfaces are orientable manifolds */
  if (!gts_surface_is_orientable (s1)) {
    fprintf (stderr, "set: surface `%s' is not an orientable manifold\n",
	     file1);
    return 1;
  }
  if (!gts_surface_is_orientable (s2)) {
    fprintf (stderr, "set: surface `%s' is not an orientable manifold\n",
	     file2);
    return 1;
  }

  /* check that the surfaces are not self-intersecting */
  if (check_self_intersection) {
    GtsSurface * self_intersects;

    self_intersects = gts_surface_is_self_intersecting (s1);
    if (self_intersects != NULL) {
      fprintf (stderr, "set: surface `%s' is self-intersecting\n", file1);
      if (verbose)
	gts_surface_print_stats (self_intersects, stderr);
      gts_surface_write (self_intersects, stdout);
      gts_object_destroy (GTS_OBJECT (self_intersects));
      return 1;
    }
    self_intersects = gts_surface_is_self_intersecting (s2);
    if (self_intersects != NULL) {
      fprintf (stderr, "set: surface `%s' is self-intersecting\n", file2);
      if (verbose)
	gts_surface_print_stats (self_intersects, stderr);
      gts_surface_write (self_intersects, stdout);
      gts_object_destroy (GTS_OBJECT (self_intersects));
      return 1;
    }
  }

  /* build bounding box tree for first surface */
  tree1 = gts_bb_tree_surface (s1);
  is_open1 = gts_surface_volume (s1) < 0. ? TRUE : FALSE;

  /* build bounding box tree for second surface */
  tree2 = gts_bb_tree_surface (s2);
  is_open2 = gts_surface_volume (s2) < 0. ? TRUE : FALSE;

  si = gts_surface_inter_new (gts_surface_inter_class (),
			      s1, s2, tree1, tree2, is_open1, is_open2);
  g_assert (gts_surface_inter_check (si, &closed));
  if (!closed) {
    fprintf (stderr,
	     "set: the intersection of `%s' and `%s' is not a closed curve\n",
	     file1, file2);
    return 1;
  }

  s3 = gts_surface_new (gts_surface_class (),
			gts_face_class (),
			gts_edge_class (),
			gts_vertex_class ());  
  if (!strcmp (operation, "union")) {
    gts_surface_inter_boolean (si, s3, GTS_1_OUT_2);
    gts_surface_inter_boolean (si, s3, GTS_2_OUT_1);
  }
  else if (!strcmp (operation, "inter")) {
    gts_surface_inter_boolean (si, s3, GTS_1_IN_2);
    gts_surface_inter_boolean (si, s3, GTS_2_IN_1);
  }
  else if (!strcmp (operation, "diff")) {
    gts_surface_inter_boolean (si, s3, GTS_1_OUT_2);
    gts_surface_inter_boolean (si, s3, GTS_2_IN_1);
    gts_surface_foreach_face (si->s2, (GtsFunc) gts_triangle_revert, NULL);
    gts_surface_foreach_face (s2, (GtsFunc) gts_triangle_revert, NULL);
  }
  else {
    fprintf (stderr, 
	     "set: operation `%s' unknown\n"
	     "Try `set --help' for more information.\n", 
	     operation);
    return 1;
  }
  
  /* check that the resulting surface is not self-intersecting */
  if (check_self_intersection) {
    GtsSurface * self_intersects;

    self_intersects = gts_surface_is_self_intersecting (s3);
    if (self_intersects != NULL) {
      fprintf (stderr, "set: the resulting surface is self-intersecting\n");
      if (verbose)
	gts_surface_print_stats (self_intersects, stderr);
      gts_surface_write (self_intersects, stdout);
      gts_object_destroy (GTS_OBJECT (self_intersects));
      return 1;
    }
  }
  /* display summary information about the resulting surface */
  if (verbose)
    gts_surface_print_stats (s3, stderr);
  /* write resulting surface to standard output */
  if (inter) {
    printf ("LIST {\n");
    g_slist_foreach (si->edges, (GFunc) write_edge, stdout);
    printf ("}\n");
  }
  else {
    GTS_POINT_CLASS (gts_vertex_class ())->binary = TRUE;
    gts_surface_write (s3, stdout);
  }

  /* destroy surfaces */
  gts_object_destroy (GTS_OBJECT (s1));
  gts_object_destroy (GTS_OBJECT (s2));
  gts_object_destroy (GTS_OBJECT (s3));
  gts_object_destroy (GTS_OBJECT (si));

  /* destroy bounding box trees (including bounding boxes) */
  gts_bb_tree_destroy (tree1, TRUE);
  gts_bb_tree_destroy (tree2, TRUE);  

  return 0;
}
Example #15
0
File: sphere.c Project: MicBosi/GTS
/* sphere - generate a triangulated unit sphere by recursive subdivision.
   First approximation is an isocahedron; each level of refinement
   increases the number of triangles by a factor of 4. 
  */
int main (int argc, char * argv[])
{
  GtsSurface * s;
  gboolean verbose = FALSE;
  guint level=4;
  int c = 0;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'},
      { NULL }
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hv", 
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hv"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'v': /* verbose */
      verbose = TRUE;
      break;
    case 'h': /* help */
      fprintf (stderr,
       "Usage: sphere [OPTION] [level]\n"
       "Generate a triangulated unit sphere by recursive subdivision.\n"
       "First approximation is an isocahedron; each level of refinement\n"
       "increases the number of triangles by a factor of 4.\n"
       "level must be a positive integer setting the recursion level\n"
       "(geodesation order), default is 4.\n"
       "\n"
       "Documentation: http://mathworld.wolfram.com/GeodesicDome.html\n"
       "\n"
       "  -v    --verbose  print statistics about the surface\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 `sphere --help' for more information.\n");
      return 1; /* failure */
    }
  }
  
  /* read level */
  if (optind < argc)
    level = atoi(argv[optind]);

  /* generate triangulated sphere */	
  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());
  gts_surface_generate_sphere (s, level);

  /* if verbose on print stats */
  if (verbose)
    gts_surface_print_stats (s, stderr);

  /* write generating surface to standard output */
  gts_surface_write (s, stdout);
  
  return 0; /* success */
}
Example #16
0
static PyObject *
new_(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
  PyObject *o;
  PygtsObject *obj;
  guint alloc_gtsobj = TRUE;
  PyObject *o1_,*o2_,*o3_;
  GtsVertex *v1=NULL, *v2=NULL, *v3=NULL;
  GtsEdge *e1=NULL,*e2=NULL,*e3=NULL,*e;
  GtsSegment *s1,*s2,*s3;
  gboolean flag=FALSE;  /* Flag when the args are gts.Point objects */
  GtsFace *f;
  GtsTriangle *t;
  guint N;

  /* Parse the args */
  if(kwds) {
    o = PyDict_GetItemString(kwds,"alloc_gtsobj");
    if(o==Py_False) {
      alloc_gtsobj = FALSE;
    }
    if(o!=NULL) {
      PyDict_DelItemString(kwds, "alloc_gtsobj");
    }
  }
  if(kwds) {
    Py_INCREF(Py_False);
    PyDict_SetItemString(kwds,"alloc_gtsobj", Py_False);
  }

  /* Allocate the gtsobj (if needed) */
  if( alloc_gtsobj ) {

    /* Parse the args */
    if( (N = PyTuple_Size(args)) < 3 ) {
      PyErr_SetString(PyExc_TypeError,"expected three Edges or three Vertices");
      return NULL;
    }
    o1_ = PyTuple_GET_ITEM(args,0);
    o2_ = PyTuple_GET_ITEM(args,1);
    o3_ = PyTuple_GET_ITEM(args,2);

    /* Convert to PygtsObjects */
    if( pygts_edge_check(o1_) ) {
      e1 = PYGTS_EDGE_AS_GTS_EDGE(o1_);
    }
    else {
      if( pygts_vertex_check(o1_) ) {
	v1 = PYGTS_VERTEX_AS_GTS_VERTEX(o1_);
	flag = TRUE;
      }
    }

    if( pygts_edge_check(o2_) ) {
      e2 = PYGTS_EDGE_AS_GTS_EDGE(o2_);
    }
    else {
      if( pygts_vertex_check(o2_) ) {
	v2 = PYGTS_VERTEX_AS_GTS_VERTEX(o2_);
	flag = TRUE;
      }
    }

    if( pygts_edge_check(o3_) ) {
      e3 = PYGTS_EDGE_AS_GTS_EDGE(o3_);
    }
    else {
      if(pygts_vertex_check(o3_)) {
	v3 = PYGTS_VERTEX_AS_GTS_VERTEX(o3_);
	flag = TRUE;
      }
    }
    
    /* Check for three edges or three vertices */
    if( !((e1!=NULL && e2!=NULL && e3!=NULL) ||
	  (v1!=NULL && v2!=NULL && v3!=NULL)) ) {
      PyErr_SetString(PyExc_TypeError,
		      "three Edge or three Vertex objects expected");
      return NULL;
    }

    if(flag) {

      /* Create gts edges */
      if( (e1 = gts_edge_new(gts_edge_class(),v1,v2)) == NULL ) {
	PyErr_SetString(PyExc_MemoryError, "could not create Edge");
	return NULL;
      }
      if( (e2 = gts_edge_new(gts_edge_class(),v2,v3)) == NULL ) {
	PyErr_SetString(PyExc_MemoryError, "could not create Edge");
	gts_object_destroy(GTS_OBJECT(e1));
	return NULL;
      }
      if( (e3 = gts_edge_new(gts_edge_class(),v3,v1)) == NULL ) {
	PyErr_SetString(PyExc_MemoryError, "could not create Edge");
	gts_object_destroy(GTS_OBJECT(e1));
	gts_object_destroy(GTS_OBJECT(e2));
	return NULL;
      }
      
      /* Check for duplicates */
      if( (e = gts_edge_is_duplicate(e1)) != NULL ) {
	gts_object_destroy(GTS_OBJECT(e1));
	e1 = e;
      }
      if( (e = gts_edge_is_duplicate(e2)) != NULL ) {
	gts_object_destroy(GTS_OBJECT(e2));
	e2 = e;
      }
      if( (e = gts_edge_is_duplicate(e3)) != NULL ) {
	gts_object_destroy(GTS_OBJECT(e3));
	e3 = e;
      }
    }
  
    /* Check that edges connect */
    s1 = GTS_SEGMENT(e1);
    s2 = GTS_SEGMENT(e2);
    s3 = GTS_SEGMENT(e3);
    if( !((s1->v1==s3->v2 && s1->v2==s2->v1 && s2->v2==s3->v1) ||
	  (s1->v1==s3->v2 && s1->v2==s2->v2 && s2->v1==s3->v1) ||
	  (s1->v1==s3->v1 && s1->v2==s2->v1 && s2->v2==s3->v2) ||
	  (s1->v2==s3->v2 && s1->v1==s2->v1 && s2->v2==s3->v1) ||
	  (s1->v1==s3->v1 && s1->v2==s2->v2 && s2->v1==s3->v2) ||
	  (s1->v2==s3->v2 && s1->v1==s2->v2 && s2->v1==s3->v1) ||
	  (s1->v2==s3->v1 && s1->v1==s2->v1 && s2->v2==s3->v2) ||
	  (s1->v2==s3->v1 && s1->v1==s2->v2 && s2->v1==s3->v2)) ) {
      PyErr_SetString(PyExc_RuntimeError, "Edges in face must connect");
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e1));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e2));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e3));
      }
      return NULL;
    }

    /* Create the GtsFace */
    if( (f = gts_face_new(gts_face_class(),e1,e2,e3)) == NULL )  {
      PyErr_SetString(PyExc_MemoryError, "could not create Face");
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e1));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e2));
      }
      if(!g_hash_table_lookup(obj_table,GTS_OBJECT(e1))) {
	gts_object_destroy(GTS_OBJECT(e3));
      }
      return NULL;
    }

    /* Check for duplicate */
    t = gts_triangle_is_duplicate(GTS_TRIANGLE(f));
    if( t != NULL ) {
      gts_object_destroy(GTS_OBJECT(f));
      if(!GTS_IS_FACE(t)) {
	PyErr_SetString(PyExc_TypeError, "expected a Face (internal error)");
      }
      f = GTS_FACE(t);
    }

    /* If corresponding PyObject found in object table, we are done */
    if( (obj=(PygtsObject*)g_hash_table_lookup(obj_table,GTS_OBJECT(f))) != NULL ) {
      Py_INCREF(obj);
      return (PyObject*)obj;
    }
  }
  
  /* Chain up */
  obj = PYGTS_OBJECT(PygtsTriangleType.tp_new(type,args,kwds));

  if( alloc_gtsobj ) {

    obj->gtsobj = GTS_OBJECT(f);

    /* Create the parent GtsSurface */
    if( (obj->gtsobj_parent = parent(GTS_FACE(obj->gtsobj))) == NULL ) {
      gts_object_destroy(obj->gtsobj);
      obj->gtsobj = NULL;
      return NULL;
    }

    pygts_object_register(PYGTS_OBJECT(obj));
  }

  return (PyObject*)obj;
}
Example #17
0
void gts_polygon_triangulate_test() 
{
	int i; 
	gdouble v[12][3] = {
		{0.0, 0.0, 0.0},
		{0.0, 3.0, 0.0},
		{3.0, 3.0, 0.0},
		{3.0, 1.0, 0.0},
		{4.0, 1.0, 0.0},
		{4.0, 3.0, 0.0},
		{5.0, 3.0, 0.0},
		{5.0, 0.0, 0.0},
		{2.0, 0.0, 0.0},
		{2.0, 2.0, 0.0},
		{1.0, 2.0, 0.0},
		{1.0, 0.0, 0.0},
	};

	GtsVector normal = {0,0,0}; 
	GtsVertex *vtx[12]; 
	GCList *polygon = NULL;
	GCList *triangle = NULL;
	GtsSurface *s, *s2; 
	
	GtsEdgePool *pool = gts_edge_pool_new(gts_edge_pool_class());
	
	gts_triangulate_test_stuff(); 
		
	for (i = 0; i < 12; ++i) {
		vtx[i] = gts_vertex_new(gts_vertex_class(), v[i][0],v[i][1],v[i][2]); 
		polygon = g_clist_append(polygon, vtx[i]);
	}

	for (i = 0; i < 3; ++i) {
		triangle = g_clist_prepend(triangle, vtx[i]); 
	}
	
	
	s = gts_surface_new(gts_surface_class(), 
			    gts_face_class(), 
			    gts_edge_class(),
			    gts_vertex_class());
	
	s2 = gts_surface_new(gts_surface_class(), 
			     gts_face_class(), 
			     gts_edge_class(),
			     gts_vertex_class());
	
	
	
	// triangulate the polygon by using its own orientation 
	polygon = gts_surface_add_polygon(s, pool, polygon, normal);
	// do some test ?
	g_assert(gts_surface_face_number(s) == 10); 
	g_debug("area  = %f", gts_surface_area(s)); 
	g_assert(gts_surface_area(s) == 11.0);
	
	
	
	gts_object_destroy(GTS_OBJECT(pool)); 
	// cleanup

	g_clist_free(triangle); 
	g_clist_free(polygon); 
	gts_object_destroy(GTS_OBJECT(s));
	gts_object_destroy(GTS_OBJECT(s2));
	g_message("Triangulate PASSED"); 
}
Example #18
0
int spheroidsToSTL(const string& out, const shared_ptr<DemField>& dem, Real tol, const string& solid, int mask, bool append, bool clipCell, bool merge){
	if(tol==0 || isnan(tol)) throw std::runtime_error("tol must be non-zero.");
	#ifndef WOO_GTS
		if(merge) throw std::runtime_error("woo.triangulated.spheroidsToSTL: merge=True only possible in builds with the 'gts' feature.");
	#endif
	// first traversal to find reference radius
	auto particleOk=[&](const shared_ptr<Particle>&p){ return (mask==0 || (p->mask & mask)) && (p->shape->isA<Sphere>() || p->shape->isA<Ellipsoid>() || p->shape->isA<Capsule>()); };
	int numTri=0;

	if(tol<0){
		LOG_DEBUG("tolerance is negative, taken as relative to minimum radius.");
		Real minRad=Inf;
		for(const auto& p: *dem->particles){
			if(particleOk(p)) minRad=min(minRad,p->shape->equivRadius());
		}
		if(isinf(minRad) || isnan(minRad)) throw std::runtime_error("Minimum radius not found (relative tolerance specified); no matching particles?");
		tol=-minRad*tol;
		LOG_DEBUG("Minimum radius "<<minRad<<".");
	}
	LOG_DEBUG("Triangulation tolerance is "<<tol);
	
	std::ofstream stl(out,append?(std::ofstream::app|std::ofstream::binary):std::ofstream::binary); // binary better, anyway
	if(!stl.good()) throw std::runtime_error("Failed to open output file "+out+" for writing.");

	Scene* scene=dem->scene;
	if(!scene) throw std::logic_error("DEM field has not associated scene?");

	// periodicity, cache that for later use
	AlignedBox3r cell;

	/*
	wasteful memory-wise, but we need to store the whole triangulation in case *merge* is in effect,
	when it is only an intermediary result and will not be output as-is
	*/
	vector<vector<Vector3r>> ppts;
	vector<vector<Vector3i>> ttri;
	vector<Particle::id_t> iid;

	for(const auto& p: *dem->particles){
		if(!particleOk(p)) continue;
		const auto sphere=dynamic_cast<Sphere*>(p->shape.get());
		const auto ellipsoid=dynamic_cast<Ellipsoid*>(p->shape.get());
		const auto capsule=dynamic_cast<Capsule*>(p->shape.get());
		vector<Vector3r> pts;
		vector<Vector3i> tri;
		if(sphere || ellipsoid){
			Real r=sphere?sphere->radius:ellipsoid->semiAxes.minCoeff();
			// 1 is for icosahedron
			int tess=ceil(M_PI/(5*acos(1-tol/r)));
			LOG_DEBUG("Tesselation level for #"<<p->id<<": "<<tess);
			tess=max(tess,0);
			auto uSphTri(CompUtils::unitSphereTri20(/*0 for icosahedron*/max(tess-1,0)));
			const auto& uPts=std::get<0>(uSphTri); // unit sphere point coords
			pts.resize(uPts.size());
			const auto& node=(p->shape->nodes[0]);
			Vector3r scale=(sphere?sphere->radius*Vector3r::Ones():ellipsoid->semiAxes);
			for(size_t i=0; i<uPts.size(); i++){
				pts[i]=node->loc2glob(uPts[i].cwiseProduct(scale));
			}
			tri=std::get<1>(uSphTri); // this makes a copy, but we need out own for capsules
		}
		if(capsule){
			#ifdef WOO_VTK
				int subdiv=max(4.,ceil(M_PI/(acos(1-tol/capsule->radius))));
				std::tie(pts,tri)=VtkExport::triangulateCapsule(static_pointer_cast<Capsule>(p->shape),subdiv);
			#else
				throw std::runtime_error("Triangulation of capsules is (for internal and entirely fixable reasons) only available when compiled with the 'vtk' features.");
			#endif
		}
		// do not write out directly, store first for later
		ppts.push_back(pts);
		ttri.push_back(tri);
		LOG_TRACE("#"<<p->id<<" triangulated: "<<tri.size()<<","<<pts.size()<<" faces,vertices.");

		if(scene->isPeriodic){
			// make sure we have aabb, in skewed coords and such
			if(!p->shape->bound){
				// this is a bit ugly, but should do the trick; otherwise we would recompute all that ourselves here
				if(sphere) Bo1_Sphere_Aabb().go(p->shape);
				else if(ellipsoid) Bo1_Ellipsoid_Aabb().go(p->shape);
				else if(capsule) Bo1_Capsule_Aabb().go(p->shape);
			}
			assert(p->shape->bound);
			const AlignedBox3r& box(p->shape->bound->box);
			AlignedBox3r cell(Vector3r::Zero(),scene->cell->getSize()); // possibly in skewed coords
			// central offset
			Vector3i off0;
			scene->cell->canonicalizePt(p->shape->nodes[0]->pos,off0); // computes off0
			Vector3i off; // offset from the original cell
			//cerr<<"#"<<p->id<<" at "<<p->shape->nodes[0]->pos.transpose()<<", off0="<<off0<<endl;
			for(off[0]=off0[0]-1; off[0]<=off0[0]+1; off[0]++) for(off[1]=off0[1]-1; off[1]<=off0[1]+1; off[1]++) for(off[2]=off0[2]-1; off[2]<=off0[2]+1; off[2]++){
				Vector3r dx=scene->cell->intrShiftPos(off);
				//cerr<<"  off="<<off.transpose()<<", dx="<<dx.transpose()<<endl;
				AlignedBox3r boxOff(box); boxOff.translate(dx);
				//cerr<<"  boxOff="<<boxOff.min()<<";"<<boxOff.max()<<" | cell="<<cell.min()<<";"<<cell.max()<<endl;
				if(boxOff.intersection(cell).isEmpty()) continue;
				// copy the entire triangulation, offset by dx
				vector<Vector3r> pts2(pts); for(auto& p: pts2) p+=dx;
				vector<Vector3i> tri2(tri); // same topology
				ppts.push_back(pts2);
				ttri.push_back(tri2);
				LOG_TRACE("  offset "<<off.transpose()<<": #"<<p->id<<": "<<tri2.size()<<","<<pts2.size()<<" faces,vertices.");
			}
		}
	}

	if(!merge){
		LOG_DEBUG("Will export (unmerged) "<<ppts.size()<<" particles to STL.");
		stl<<"solid "<<solid<<"\n";
		for(size_t i=0; i<ppts.size(); i++){
			const auto& pts(ppts[i]);
			const auto& tri(ttri[i]);
			LOG_TRACE("Exporting "<<i<<" with "<<tri.size()<<" faces.");
			for(const Vector3i& t: tri){
				Vector3r pp[]={pts[t[0]],pts[t[1]],pts[t[2]]};
				// skip triangles which are entirely out of the canonical periodic cell
				if(scene->isPeriodic && clipCell && (!scene->cell->isCanonical(pp[0]) && !scene->cell->isCanonical(pp[1]) && !scene->cell->isCanonical(pp[2]))) continue;
				numTri++;
				Vector3r n=(pp[1]-pp[0]).cross(pp[2]-pp[1]).normalized();
				stl<<"  facet normal "<<n.x()<<" "<<n.y()<<" "<<n.z()<<"\n";
				stl<<"    outer loop\n";
				for(auto p: {pp[0],pp[1],pp[2]}){
					stl<<"      vertex "<<p[0]<<" "<<p[1]<<" "<<p[2]<<"\n";
				}
				stl<<"    endloop\n";
				stl<<"  endfacet\n";
			}
		}
		stl<<"endsolid "<<solid<<"\n";
		stl.close();
		return numTri;
	}

#if WOO_GTS
	/*****
	Convert all triangulation to GTS surfaces, find their distances, isolate connected components,
	merge these components incrementally and write to STL
	*****/

	// total number of points
	const size_t N(ppts.size());
	// bounds for collision detection
	struct Bound{
		Bound(Real _coord, int _id, bool _isMin): coord(_coord), id(_id), isMin(_isMin){};
		Bound(): coord(NaN), id(-1), isMin(false){}; // just for allocation
		Real coord;
		int id;
		bool isMin;
		bool operator<(const Bound& b) const { return coord<b.coord; }
	};
	vector<Bound> bounds[3]={vector<Bound>(2*N),vector<Bound>(2*N),vector<Bound>(2*N)};
	/* construct GTS surface objects; all objects must be deleted explicitly! */
	vector<GtsSurface*> ssurf(N);
	vector<vector<GtsVertex*>> vvert(N);
	vector<vector<GtsEdge*>> eedge(N);
	vector<AlignedBox3r> boxes(N);
	for(size_t i=0; i<N; i++){
		LOG_TRACE("** Creating GTS surface for #"<<i<<", with "<<ttri[i].size()<<" faces, "<<ppts[i].size()<<" vertices.");
		AlignedBox3r box;
		// new surface object
		ssurf[i]=gts_surface_new(gts_surface_class(),gts_face_class(),gts_edge_class(),gts_vertex_class());
		// copy over all vertices
		vvert[i].reserve(ppts[i].size());
		eedge[i].reserve(size_t(1.5*ttri[i].size())); // each triangle consumes 1.5 edges, for closed surfs
		for(size_t v=0; v<ppts[i].size(); v++){
			vvert[i].push_back(gts_vertex_new(gts_vertex_class(),ppts[i][v][0],ppts[i][v][1],ppts[i][v][2]));
			box.extend(ppts[i][v]);
		}
		// create faces, and create edges on the fly as needed
		std::map<std::pair<int,int>,int> edgeIndices;
		for(size_t t=0; t<ttri[i].size(); t++){
			//const Vector3i& t(ttri[i][t]);
			//LOG_TRACE("Face with vertices "<<ttri[i][t][0]<<","<<ttri[i][t][1]<<","<<ttri[i][t][2]);
			Vector3i eIxs;
			for(int a:{0,1,2}){
				int A(ttri[i][t][a]), B(ttri[i][t][(a+1)%3]);
				auto AB=std::make_pair(min(A,B),max(A,B));
				auto ABI=edgeIndices.find(AB);
				if(ABI==edgeIndices.end()){ // this edge not created yet
					edgeIndices[AB]=eedge[i].size(); // last index 
					eIxs[a]=eedge[i].size();
					//LOG_TRACE("  New edge #"<<eIxs[a]<<": "<<A<<"--"<<B<<" (length "<<(ppts[i][A]-ppts[i][B]).norm()<<")");
					eedge[i].push_back(gts_edge_new(gts_edge_class(),vvert[i][A],vvert[i][B]));
				} else {
					eIxs[a]=ABI->second;
					//LOG_TRACE("  Found edge #"<<ABI->second<<" for "<<A<<"--"<<B);
				}
			}
			//LOG_TRACE("  New face: edges "<<eIxs[0]<<"--"<<eIxs[1]<<"--"<<eIxs[2]);
			GtsFace* face=gts_face_new(gts_face_class(),eedge[i][eIxs[0]],eedge[i][eIxs[1]],eedge[i][eIxs[2]]);
			gts_surface_add_face(ssurf[i],face);
		}
		// make sure the surface is OK
		if(!gts_surface_is_orientable(ssurf[i])) LOG_ERROR("Surface of #"+to_string(iid[i])+" is not orientable (expect troubles).");
		if(!gts_surface_is_closed(ssurf[i])) LOG_ERROR("Surface of #"+to_string(iid[i])+" is not closed (expect troubles).");
		assert(!gts_surface_is_self_intersecting(ssurf[i]));
		// copy bounds
		LOG_TRACE("Setting bounds of surf #"<<i);
		boxes[i]=box;
		for(int ax:{0,1,2}){
			bounds[ax][2*i+0]=Bound(box.min()[ax],/*id*/i,/*isMin*/true);
			bounds[ax][2*i+1]=Bound(box.max()[ax],/*id*/i,/*isMin*/false);
		}
	}

	/*
	broad-phase collision detection between GTS surfaces
	only those will be probed with exact algorithms below and merged if needed
	*/
	for(int ax:{0,1,2}) std::sort(bounds[ax].begin(),bounds[ax].end());
	vector<Bound>& bb(bounds[0]); // run the search along x-axis, does not matter really
	std::list<std::pair<int,int>> int0; // broad-phase intersections
	for(size_t i=0; i<2*N; i++){
		if(!bb[i].isMin) continue; // only start with lower bound
		// go up to the upper bound, but handle overflow safely (no idea why it would happen here) as well
		for(size_t j=i+1; j<2*N && bb[j].id!=bb[i].id; j++){
			if(bb[j].isMin) continue; // this is handled by symmetry
			#if EIGEN_VERSION_AT_LEAST(3,2,5)
				if(!boxes[bb[i].id].intersects(boxes[bb[j].id])) continue; // no intersection along all axes
			#else
				// old, less elegant
				if(boxes[bb[i].id].intersection(boxes[bb[j].id]).isEmpty()) continue; 
			#endif
			int0.push_back(std::make_pair(min(bb[i].id,bb[j].id),max(bb[i].id,bb[j].id)));
			LOG_TRACE("Broad-phase collision "<<int0.back().first<<"+"<<int0.back().second);
		}
	}

	/*
	narrow-phase collision detection between GTS surface
	this must be done via gts_surface_inter_new, since gts_surface_distance always succeeds
	*/
	std::list<std::pair<int,int>> int1;
	for(const std::pair<int,int> ij: int0){
		LOG_TRACE("Testing narrow-phase collision "<<ij.first<<"+"<<ij.second);
		#if 0
			GtsRange gr1, gr2;
			gts_surface_distance(ssurf[ij.first],ssurf[ij.second],/*delta ??*/(gfloat).2,&gr1,&gr2);
			if(gr1.min>0 && gr2.min>0) continue;
			LOG_TRACE("  GTS reports collision "<<ij.first<<"+"<<ij.second<<" (min. distances "<<gr1.min<<", "<<gr2.min);
		#else
			GtsSurface *s1(ssurf[ij.first]), *s2(ssurf[ij.second]);
			GNode* t1=gts_bb_tree_surface(s1);
			GNode* t2=gts_bb_tree_surface(s2);
			GtsSurfaceInter* I=gts_surface_inter_new(gts_surface_inter_class(),s1,s2,t1,t2,/*is_open_1*/false,/*is_open_2*/false);
			GSList* l=gts_surface_intersection(s1,s2,t1,t2); // list of edges describing intersection
			int n1=g_slist_length(l);
			// extra check by looking at number of faces of the intersected surface
			#if 1
				GtsSurface* s12=gts_surface_new(gts_surface_class(),gts_face_class(),gts_edge_class(),gts_vertex_class());
				gts_surface_inter_boolean(I,s12,GTS_1_OUT_2);
				gts_surface_inter_boolean(I,s12,GTS_2_OUT_1);
				int n2=gts_surface_face_number(s12);
				gts_object_destroy(GTS_OBJECT(s12));
			#endif
			gts_bb_tree_destroy(t1,TRUE);
			gts_bb_tree_destroy(t2,TRUE);
			gts_object_destroy(GTS_OBJECT(I));
			g_slist_free(l);
			if(n1==0) continue;
			#if 1
				if(n2==0){ LOG_ERROR("n1==0 but n2=="<<n2<<" (no narrow-phase collision)"); continue; }
			#endif
			LOG_TRACE("  GTS reports collision "<<ij.first<<"+"<<ij.second<<" ("<<n<<" edges describe the intersection)");
		#endif
		int1.push_back(ij);
	}
	/*
	connected components on the graph: graph nodes are 0…(N-1), graph edges are in int1
	see http://stackoverflow.com/a/37195784/761090
	*/
	typedef boost::subgraph<boost::adjacency_list<boost::vecS,boost::vecS,boost::undirectedS,boost::property<boost::vertex_index_t,int>,boost::property<boost::edge_index_t,int>>> Graph;
	Graph graph(N);
	for(const auto& ij: int1) boost::add_edge(ij.first,ij.second,graph);
	vector<size_t> clusters(boost::num_vertices(graph));
	size_t numClusters=boost::connected_components(graph,clusters.data());
	for(size_t n=0; n<numClusters; n++){
		// beginning cluster #n
		// first, count how many surfaces are in this cluster; if 1, things are easier
		int numThisCluster=0; int cluster1st=-1;
		for(size_t i=0; i<N; i++){ if(clusters[i]!=n) continue; numThisCluster++; if(cluster1st<0) cluster1st=(int)i; }
		GtsSurface* clusterSurf=NULL;
		LOG_DEBUG("Cluster "<<n<<" has "<<numThisCluster<<" surfaces.");
		if(numThisCluster==1){
			clusterSurf=ssurf[cluster1st]; 
		} else {
			clusterSurf=ssurf[cluster1st]; // surface of the cluster itself
			LOG_TRACE("  Initial cluster surface from "<<cluster1st<<".");
			/* composed surface */
			for(size_t i=0; i<N; i++){
				if(clusters[i]!=n || ((int)i)==cluster1st) continue;
				LOG_TRACE("   Adding "<<i<<" to the cluster");
				// ssurf[i] now belongs to cluster #n
				// trees need to be rebuild every time anyway, since the merged surface keeps changing in every cycle
				//if(gts_surface_face_number(clusterSurf)==0) LOG_ERROR("clusterSurf has 0 faces.");
				//if(gts_surface_face_number(ssurf[i])==0) LOG_ERROR("Surface #"<<i<<" has 0 faces.");
				GNode* t1=gts_bb_tree_surface(clusterSurf);
				GNode* t2=gts_bb_tree_surface(ssurf[i]);
				GtsSurfaceInter* I=gts_surface_inter_new(gts_surface_inter_class(),clusterSurf,ssurf[i],t1,t2,/*is_open_1*/false,/*is_open_2*/false);
				GtsSurface* merged=gts_surface_new(gts_surface_class(),gts_face_class(),gts_edge_class(),gts_vertex_class());
				gts_surface_inter_boolean(I,merged,GTS_1_OUT_2);
				gts_surface_inter_boolean(I,merged,GTS_2_OUT_1);
				gts_object_destroy(GTS_OBJECT(I));
				gts_bb_tree_destroy(t1,TRUE);
				gts_bb_tree_destroy(t2,TRUE);
				if(gts_surface_face_number(merged)==0){
					LOG_ERROR("Cluster #"<<n<<": 0 faces after fusing #"<<i<<" (why?), adding #"<<i<<" separately!");
					// this will cause an extra 1-particle cluster to be created
					clusters[i]=numClusters;
					numClusters+=1;
				} else {
					// not from global vectors (cleanup at the end), explicit delete!
					if(clusterSurf!=ssurf[cluster1st]) gts_object_destroy(GTS_OBJECT(clusterSurf));
					clusterSurf=merged;
				}
			}
		}
		#if 0
			LOG_TRACE("  GTS surface cleanups...");
	 		pygts_vertex_cleanup(clusterSurf,.1*tol); // cleanup 10× smaller than tolerance
		   pygts_edge_cleanup(clusterSurf);
	      pygts_face_cleanup(clusterSurf);
		#endif
		LOG_TRACE("  STL: cluster "<<n<<" output");
		stl<<"solid "<<solid<<"_"<<n<<"\n";
		/* output cluster to STL here */
		_gts_face_to_stl_data data(stl,scene,clipCell,numTri);
		gts_surface_foreach_face(clusterSurf,(GtsFunc)_gts_face_to_stl,(gpointer)&data);
		stl<<"endsolid\n";
		if(clusterSurf!=ssurf[cluster1st]) gts_object_destroy(GTS_OBJECT(clusterSurf));
	}
	// this deallocates also edges and vertices
	for(size_t i=0; i<ssurf.size(); i++) gts_object_destroy(GTS_OBJECT(ssurf[i]));
	return numTri;
#endif /* WOO_GTS */
}
Example #19
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;
}
Example #20
0
File: optimize.c Project: bert/gts
int main (int argc, char * argv[])
{
    GtsSurface * s;
    gboolean verbose = FALSE;
    gdouble threshold;
    int c = 0;
    GtsFile * fp;
    GtsRange angle;

    if (!setlocale (LC_ALL, "POSIX"))
        g_warning ("cannot set locale to POSIX");

    /* parse options using getopt */
    while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
        static struct option long_options[] = {
            {"help", no_argument, NULL, 'h'},
            {"verbose", no_argument, NULL, 'v'},
            { NULL }
        };
        int option_index = 0;
        switch ((c = getopt_long (argc, argv, "hv",
                                  long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
        switch ((c = getopt (argc, argv, "hv"))) {
#endif /* not HAVE_GETOPT_LONG */
        case 'v': /* verbose */
            verbose = TRUE;
            break;
        case 'h': /* help */
            fprintf (stderr,
                     "Usage: optimize [OPTION] THRESHOLD < FILE\n"
                     "\n"
                     "  -v      --verbose  print statistics about the surface\n"
                     "  -h      --help     display this help and exit\n"
                     "\n"
                     "Report bugs to %s\n",
                     GTS_MAINTAINER);
            return 0; /* success */
            break;
        case '?': /* wrong options */
            fprintf (stderr, "Try `optimize --help' for more information.\n");
            return 1; /* failure */
        }
    }

    if (optind >= argc) { /* missing threshold */
        fprintf (stderr,
                 "optimize: missing THRESHOLD\n"
                 "Try `optimize --help' for more information.\n");
        return 1; /* failure */
    }
    threshold = strtod (argv[optind], NULL);

    if (threshold < 0.0) { /* threshold must be positive */
        fprintf (stderr,
                 "optimize: THRESHOLD must be >= 0.0\n"
                 "Try `optimize --help' for more information.\n");
        return 1; /* failure */
    }

    /* read surface in */
    s = gts_surface_new (gts_surface_class (),
                         gts_face_class (),
                         gts_edge_class (),
                         gts_vertex_class ());
    fp = gts_file_new (stdin);
    if (gts_surface_read (s, fp)) {
        fputs ("optimize: file on standard input is not a valid GTS file\n",
               stderr);
        fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
        return 1; /* failure */
    }

    /* if verbose on print stats */
    if (verbose) {
        gts_surface_print_stats (s, stderr);
        gts_range_init (&angle);
        gts_surface_foreach_edge (s, (GtsFunc) angle_stats, &angle);
        gts_range_update (&angle);
        fputs ("#   angle : ", stderr);
        gts_range_print (&angle, stderr);
        fputc ('\n', stderr);
    }

    surface_optimize (s, -threshold);

    /* if verbose on print stats */
    if (verbose) {
        gts_surface_print_stats (s, stderr);
        gts_range_init (&angle);
        gts_surface_foreach_edge (s, (GtsFunc) angle_stats, &angle);
        gts_range_update (&angle);
        fputs ("#   angle : ", stderr);
        gts_range_print (&angle, stderr);
        fputc ('\n', stderr);
    }

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

    return 0; /* success */
}
Example #21
0
/* stripe - Turns the input surface into triangle strips and outputs a
   Geomview representation of the result. */
int main (int argc, char * argv[])
{
    GtsSurface * s;
    GSList * strips = NULL, * i;
    gboolean verbose = FALSE;
    int c = 0;
    GtsFile * fp;

    /* parse options using getopt */
    while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
        static struct option long_options[] = {
            {"help", no_argument, NULL, 'h'},
            {"verbose", no_argument, NULL, 'v'}
        };
        int option_index = 0;
        switch ((c = getopt_long (argc, argv, "hv",
                                  long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
        switch ((c = getopt (argc, argv, "hv"))) {
#endif /* not HAVE_GETOPT_LONG */
        case 'v': /* verbose */
            verbose = TRUE;
            break;
        case 'h': /* help */
            fprintf (stderr,
                     "Usage: stripe [OPTION] < FILE\n"
                     "Turns the input surface into triangle strips and outputs a\n"
                     "Geomview representation of the result.\n"
                     "\n"
                     "  -v      --verbose  print statistics about the surface and strips\n"
                     "  -h      --help     display this help and exit\n"
                     "\n"
                     "Report bugs to %s\n",
                     GTS_MAINTAINER);
            return 0; /* success */
            break;
        case '?': /* wrong options */
            fprintf (stderr, "Try `stripe --help' for more information.\n");
            return 1; /* failure */
        }
    }

    /* read surface in */
    s = gts_surface_new (gts_surface_class (),
                         gts_face_class (),
                         gts_edge_class (),
                         gts_vertex_class ());
    fp = gts_file_new (stdin);
    if (gts_surface_read (s, fp)) {
        fputs ("stripe: file on standard input is not a valid GTS file\n",
               stderr);
        fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
        return 1; /* failure */
    }
    gts_file_destroy (fp);

    if (verbose)
        gts_surface_print_stats (s, stderr);

    strips = gts_surface_strip (s);

    /* if verbose on print stats */
    if (verbose) {
        GtsRange l;

        gts_range_init (&l);
        i = strips;
        while (i) {
            gts_range_add_value (&l, g_slist_length (i->data));
            i = i->next;
        }
        gts_range_update (&l);
        fprintf (stderr, "# Strips: %d\n#   length : ", l.n);
        gts_range_print (&l, stderr);
        fputc ('\n', stderr);
    }

    puts ("LIST {\n");
    i = strips;
    while (i) {
        GList * j = i->data;
        GtsTriangle * oldt = NULL;
        GtsColor c;

        c.r = rand ()/(gdouble) RAND_MAX;
        c.g = rand ()/(gdouble) RAND_MAX;
        c.b = rand ()/(gdouble) RAND_MAX;
        while (j) {
            GtsTriangle * t = j->data;
            GtsPoint
            * p1 = GTS_POINT (GTS_SEGMENT (t->e1)->v1),
              * p2 = GTS_POINT (GTS_SEGMENT (t->e1)->v2),
                * p3 = GTS_POINT (gts_triangle_vertex (t));

            printf ("OFF 3 1 3\n%g %g %g\n%g %g %g\n%g %g %g\n3 0 1 2 %g %g %g\n",
                    p1->x, p1->y, p1->z,
                    p2->x, p2->y, p2->z,
                    p3->x, p3->y, p3->z,
                    c.r, c.g, c.b);
            if (oldt) {
                GtsSegment * cs = GTS_SEGMENT (gts_triangles_common_edge (t, oldt));
                GtsPoint
                * op1 = GTS_POINT (GTS_SEGMENT (oldt->e1)->v1),
                  * op2 = GTS_POINT (GTS_SEGMENT (oldt->e1)->v2),
                    * op3 = GTS_POINT (gts_triangle_vertex (oldt));

                printf ("VECT 1 3 0 3 0 %g %g %g %g %g %g %g %g %g\n",
                        (op1->x + op2->x + op3->x)/3.,
                        (op1->y + op2->y + op3->y)/3.,
                        (op1->z + op2->z + op3->z)/3.,
                        (GTS_POINT (cs->v1)->x + GTS_POINT (cs->v2)->x)/2.,
                        (GTS_POINT (cs->v1)->y + GTS_POINT (cs->v2)->y)/2.,
                        (GTS_POINT (cs->v1)->z + GTS_POINT (cs->v2)->z)/2.,
                        (p1->x + p2->x + p3->x)/3.,
                        (p1->y + p2->y + p3->y)/3.,
                        (p1->z + p2->z + p3->z)/3.);
            }
            oldt = t;
            j = j->next;
        }
        i = i->next;
    }
    puts ("}\n");

    return 0; /* success */
}
Example #22
0
/* coarsen - produce a coarsened version of the input */
int main (int argc, char * argv[])
{
  GtsSurface * s;
  GtsPSurface * ps = NULL;
  gboolean verbose = FALSE;
  gboolean progressive = FALSE;
  gboolean log_cost = FALSE;
  guint number = 0;
  gdouble cmax = 0.0;
  StopOptions stop = NUMBER;
  CostOptions cost = COST_OPTIMIZED;
  MidvertexOptions mid = OPTIMIZED;
  GtsKeyFunc cost_func = NULL;
  GtsCoarsenFunc coarsen_func = NULL;
  GtsStopFunc stop_func = NULL;
  gpointer stop_data = NULL;
  int c = 0;
  GtsFile * fp;
  gdouble fold = PI/180.;
  GtsVolumeOptimizedParams params = { 0.5, 0.5, 0. };
  gpointer coarsen_data = NULL, cost_data = NULL;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"angle", no_argument, NULL, 'a'},
      {"progressive", no_argument, NULL, 'p'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'},
      {"number", required_argument, NULL, 'n'},
      {"length", no_argument, NULL, 'l'},
      {"midvertex", no_argument, NULL, 'm'},
      {"cost", required_argument, NULL, 'c'},
      {"fold", required_argument, NULL, 'f'},
      {"vweight", required_argument, NULL, 'w'},
      {"bweight", required_argument, NULL, 'b'},
      {"sweight", required_argument, NULL, 's'},
      {"log", no_argument, NULL, 'L'}
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvmc:n:lpf:w:b:s:La",
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvmc:n:lpf:w:b:s:La"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'a': /* angle */
      cost = COST_ANGLE;
      break;
    case 'L': /* log */
      log_cost = TRUE;
      break;
    case 'p': /* write progressive surface */
      progressive = TRUE;
      break;
    case 'n': /* stop by number */
      stop = NUMBER;
      number = atoi (optarg);
      break;
    case 'c': /* stop by cost */
      stop = COST;
      cmax = atof (optarg);
      break;
    case 'v': /* verbose */
      verbose = TRUE;
      break;
    case 'm': /* midvertex */
      mid = MIDVERTEX;
      break;
    case 'l': /* cost is length */
      cost = COST_LENGTH;
      break;
    case 'f': /* fold angle */
      fold = atof (optarg)*PI/180.;
      break;
    case 'w': /* volume optimized weight */
      params.volume_weight = atof (optarg);
      break;
    case 'b': /* boundary optimized weight */
      params.boundary_weight = atof (optarg);
      break;
    case 's': /* shape optimized weight */
      params.shape_weight = atof (optarg);
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: coarsen [OPTION] < file.gts\n"
	     "Construct a coarsened version of the input.\n"
	     "\n"
	     "  -n N, --number=N    stop the coarsening process if the number of\n"
	     "                      edges was to fall below N\n"
	     "  -c C, --cost=C      stop the coarsening process if the cost of collapsing\n"
	     "                      an edge is larger than C\n"
	     "  -m    --midvertex   use midvertex as replacement vertex\n"
	     "                      default is volume optimized point\n"
	     "  -l    --length      use length^2 as cost function\n"
	     "                      default is optimized point cost\n"
	     "  -f F, --fold=F      set maximum fold angle to F degrees\n"
	     "                      default is one degree\n"
	     "  -w W, --vweight=W   set weight used for volume optimization\n"
	     "                      default is 0.5\n"
	     "  -b W, --bweight=W   set weight used for boundary optimization\n"
	     "                      default is 0.5\n"
	     "  -s W, --sweight=W   set weight used for shape optimization\n"
	     "                      default is 0.0\n"
	     "  -p    --progressive write progressive surface file\n"
	     "  -L    --log         logs the evolution of the cost\n"
	     "  -v    --verbose     print statistics about the surface\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 `coarsen --help' for more information.\n");
      return 1; /* failure */
    }
  }
  
  /* read surface in */
  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());
  fp = gts_file_new (stdin);
  if (gts_surface_read (s, fp)) {
    fputs ("coarsen: the file on standard input is not a valid GTS file\n", 
	   stderr);
    fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
    return 1; /* failure */
  }

  /* if verbose on print stats */
  if (verbose) {
    gts_surface_print_stats (s, stderr);
    fprintf (stderr, "# volume: %g area: %g\n", 
	     gts_surface_volume (s), gts_surface_area (s));
  }

  /* select the right coarsening process */
  switch (cost) {
  case COST_OPTIMIZED: 
    cost_func = (GtsKeyFunc) gts_volume_optimized_cost; 
    cost_data = &params;
    break;
  case COST_LENGTH:
    cost_func = NULL; break;
  case COST_ANGLE:
    cost_func = (GtsKeyFunc) cost_angle; break;
  default:
    g_assert_not_reached ();
  }
  switch (mid) {
  case MIDVERTEX:
    coarsen_func = NULL; 
    break;
  case OPTIMIZED:
    coarsen_func = (GtsCoarsenFunc) gts_volume_optimized_vertex; 
    coarsen_data = &params;
    break;
  default:
    g_assert_not_reached ();
  }
  if (log_cost)
    stop_func = (GtsStopFunc) stop_log_cost;
  else {
    switch (stop) {
    case NUMBER:
      if (verbose)
	stop_func = (GtsStopFunc) stop_number_verbose;
      else
	stop_func = (GtsStopFunc) gts_coarsen_stop_number; 
      stop_data = &number;
      break;
    case COST:
      if (verbose)
	stop_func = (GtsStopFunc) stop_cost_verbose;
      else
	stop_func = (GtsStopFunc) gts_coarsen_stop_cost; 
      stop_data = &cmax;
      break;
    default:
      g_assert_not_reached ();
    }
  }
  if (progressive)
    ps = gts_psurface_new (gts_psurface_class (),
			   s, gts_split_class (),
			   cost_func, cost_data,
			   coarsen_func, coarsen_data,
			   stop_func, stop_data, 
			   fold);
  else
    gts_surface_coarsen (s, 
			 cost_func, cost_data, 
			 coarsen_func, coarsen_data, 
			 stop_func, stop_data, fold);

  /* if verbose on print stats */
  if (verbose) {
    fputc ('\n', stderr);
    gts_surface_print_stats (s, stderr);
    fprintf (stderr, "# volume: %g area: %g\n", 
	     gts_surface_volume (s), gts_surface_area (s));
  }

  /* write resulting surface to standard output */
  if (progressive)
    gts_psurface_write (ps, stdout);
  else
    gts_surface_write (s, stdout);

  return 0; /* success */
}
Example #23
0
int main (int argc, char * argv[])
{
  gboolean verbose = FALSE;
  gboolean triangulate_holes = TRUE;
  gboolean write_holes = FALSE;
  int c = 0;
  CartesianGrid * grid;
  guint line = 0;
  GtsSurface * s;
  GTimer * timer;

  if (!setlocale (LC_ALL, "POSIX"))
    g_warning ("cannot set locale to POSIX");

  /* parse options using getopt */
  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"holes", no_argument, NULL, 'H'},
      {"keep", no_argument, NULL, 'k'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'},
      { NULL }
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvHk", 
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvHk"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'H': /* holes */
      write_holes = TRUE;
      break;
    case 'k': /* keep */
      triangulate_holes = FALSE;
      break;
    case 'v': /* verbose */
      verbose = TRUE;
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: cartesian [OPTION] < FILE\n"
	     "Triangulates vertices of a regular cartesian mesh\n"
	     "(possibly containing holes)\n"
	     "\n"
	     "  -k    --keep     keep holes\n"
	     "  -H    --holes    write holes only\n"
	     "  -v    --verbose  print statistics about the surface\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 `cartesian --help' for more information.\n");
      return 1; /* failure */
    }
  }
  
  grid = cartesian_grid_read (gts_vertex_class (), &line);
  if (grid == NULL) {
    fprintf (stderr, 
	   "cartesian: file on standard input is not a valid cartesian grid\n"
	   "error at line %u\n", line);
    return 1;
  }

  timer = g_timer_new ();
  g_timer_start (timer);
  s = gts_surface_new (gts_surface_class (), 
		       gts_face_class (), 
		       gts_edge_class (), 
		       gts_vertex_class ());
  cartesian_grid_triangulate (grid, s);
  if (triangulate_holes) {    
    GtsSurface * holes = cartesian_grid_triangulate_holes (grid, s);
    if (write_holes) {
      gts_object_destroy (GTS_OBJECT (s));
      s = holes;
    }
    else
      gts_surface_merge (s, holes);
  }
  g_timer_stop (timer);
  
  if (verbose) {
    gts_surface_print_stats (s, stderr);
    fprintf (stderr, "# Triangulation time: %g s speed: %.0f vertex/s\n", 
	     g_timer_elapsed (timer, NULL),
	     gts_surface_vertex_number (s)/g_timer_elapsed (timer, NULL));
  }

  gts_surface_write (s, stdout);

  return 0; /* success */
}
Example #24
0
int main (int argc, char * argv[])
{
  int c = 0;
  gboolean verbose = FALSE;
  gboolean revert  = FALSE;  
  GtsSurface * s;
  GtsFile * fp;

  while (c != EOF) {
#ifdef HAVE_GETOPT_LONG
    static struct option long_options[] = {
      {"revert", no_argument, NULL, 'r'},
      {"help", no_argument, NULL, 'h'},
      {"verbose", no_argument, NULL, 'v'}
    };
    int option_index = 0;
    switch ((c = getopt_long (argc, argv, "hvr",
			      long_options, &option_index))) {
#else /* not HAVE_GETOPT_LONG */
    switch ((c = getopt (argc, argv, "hvr"))) {
#endif /* not HAVE_GETOPT_LONG */
    case 'r': /* revert */
      revert = TRUE;
      break;
    case 'h': /* help */
      fprintf (stderr,
             "Usage: gts2stl [OPTION]... < input.gts > output.stl\n"
	     "Convert a GTS file to STL format.\n"
	     "\n"
	     "  -r,     --revert       revert face normals\n"
	     "  -v,     --verbose      display surface statistics\n"
	     "  -h,     --help         display this help and exit\n"
	     "\n"
	     "Report bugs to %s\n",
	     GTS_MAINTAINER);
      return 0;
      break;
    case 'v':
      verbose = TRUE;
      break;
    case '?': /* wrong options */
      fprintf (stderr, "Try `gts2stl --help' for more information.\n");
      return 1;
    }
  }

  s = gts_surface_new (gts_surface_class (),
		       gts_face_class (),
		       gts_edge_class (),
		       gts_vertex_class ());
  fp = gts_file_new (stdin);
  if (gts_surface_read (s, fp)) {
    fputs ("gts2stl: file on standard input is not a valid GTS file\n", 
	   stderr);
    fprintf (stderr, "stdin:%d:%d: %s\n", fp->line, fp->pos, fp->error);
    return 1; /* failure */
  }

  if (revert)
    gts_surface_foreach_face (s, (GtsFunc) gts_triangle_revert, NULL);
  if (verbose)
    gts_surface_print_stats (s, stderr);

  puts ("solid");
  gts_surface_foreach_face (s, (GtsFunc) write_face, NULL);
  puts ("endsolid");

  return 0;
}