/* * face.c - Data structure and handling of one face of a part * * Written 2010 by Werner Almesberger * Copyright 2010 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #include #include #include #include #include #include #include #include "util.h" #include "array.h" #include "histo.h" #include "face.h" #define CACHE_DIR ".cache" #define DEFAULT_STEP 1 /* 1 mm */ #define MIN_STEP 0.005 /* 5 um */ struct coord { float x, y, z; }; static struct coord *load_file(const char *name) { FILE *file; struct coord *v, *n; int s; if (!strcmp(name, "-")) { file = stdin; } else { int len; len = strlen(name); if (len > 4 && !strcmp(name+len-4, ".bz2")) { char tmp[1000]; /* @@@ enough */ sprintf(tmp, "bzcat \"%s\"", name); file = popen(tmp, "r"); if (!file) { perror(tmp); exit(1); } } else { file = fopen(name, "r"); if (!file) { perror(name); exit(1); } } } v = n = alloc_type(struct coord); s = 1; while (fscanf(file, "%f,%f,%f\r\n", &n->x, &n->y, &n->z) == 3) { n++; if (n-v == s) { struct coord *tmp; s += s; tmp = realloc(v, sizeof(struct coord)*s); if (!tmp) { perror("realloc"); exit(1); } n = n-v+tmp; v = tmp; } } if (file != stdin) (void) fclose(file); n->x = n->y = n->z = 0; return v; } static void adjust_step(double *step, double delta) { double n = round(delta/MIN_STEP); double s = n*MIN_STEP; if (n && s < *step) *step = s; } static struct face *read_file(const char *name) { struct coord *v, *p; struct face *f; struct histo *h; int xi, yi, zi; v = load_file(name); f = alloc_type(struct face); f->a = new_array(); /* * Hack: the MDX-15 measures bumps along the x axis with 25 um * resolution, so we just ignore the x resultion we find and use the * y resolution instead. */ f->x_step = f->y_step =f->z_step = DEFAULT_STEP; for (p = v; p[1].x || p[1].y || p[1].z; p++) { adjust_step(&f->y_step, fabs(p[0].y-p[1].y)); adjust_step(&f->z_step, fabs(p[0].z-p[1].z)); } f->x_step = f->y_step; for (p = v; p->x || p->y || p->z; p++) { xi = round(p->x/f->x_step); yi = round(p->y/f->y_step); zi = round(p->z/f->z_step); set(f->a, xi, yi, zi); } free(v); f->sx = f->a->max_x-f->a->min_x+1; f->sy = f->a->max_y-f->a->min_y+1; f->cx = (f->a->min_x+f->a->max_x)/2; f->cy = (f->a->min_y+f->a->max_y)/2; h = make_histo(f->a); f->z_ref = f->a->min_z+median(h); free_histo(h); f->fx = f->fy = 0; f->m.a[0][0] = f->m.a[1][1] = 1; f->m.a[0][1] = f->m.a[1][0] = 0; f->m.b[0] = f->m.b[1] = 0; fprintf(stderr, "%g %g %g\n", f->x_step, f->y_step, f->z_step); fprintf(stderr, "%d-%d / %d-%d / %d-%d\n", f->a->min_x, f->a->max_x, f->a->min_y, f->a->max_y, f->a->min_z, f->a->max_z); return f; } struct face *read_face(const char *name) { const char *p; int cwd; struct face *face; if (strncmp(name, "http:", 5) && strncmp(name, "https:", 6)) return read_file(name); p = strrchr(name, '/'); if (!p || !p[1]) { fprintf(stderr, "malformed URL: \"%s\"\n", name); exit(1); } cwd = open(".", O_RDONLY); if (cwd < 0) { perror("."); exit(1); } if (chdir(CACHE_DIR) < 0) { perror(CACHE_DIR); exit(1); } if (access(p+1, R_OK) < 0) { char tmp[1000]; /* @@@ enough */ int res; sprintf(tmp, "wget '%s'", name); res = system(tmp); if (res < 0) { perror("system"); exit(1); } if (!WIFEXITED(res) || WEXITSTATUS(res)) { fprintf(stderr, "%s: status %d\n", tmp, res); exit(1); } } face = read_file(p+1); if (fchdir(cwd) < 0) { perror("fchdir"); exit(1); } return face; }