/* * project.c - Load and save solidify project descriptions * * 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 "util.h" #include "face.h" #include "solid.h" #include "project.h" static struct project *make_project(const char *name, const char *top, const char *bottom, double dist_mm) { struct project *prj; prj = alloc_type(struct project); prj->name = stralloc(name); prj->top = stralloc(top); prj->bottom = stralloc(bottom); prj->s.a = read_face(top); prj->s.b = read_face(bottom); if (prj->s.a->x_step != prj->s.a->x_step || prj->s.a->y_step != prj->s.a->y_step || prj->s.a->z_step != prj->s.a->z_step) { fprintf(stderr, "both faces must have the same resolution\n"); exit(1); } prj->s.dist = dist_mm/prj->s.a->z_step; return prj; } struct project *new_project(const char *name, const char *top, const char *bottom, double dist_mm) { FILE *file; file = fopen(name, "r"); if (file) { fprintf(stderr, "%s: already exists\n", name); exit(1); } return make_project(name, top, bottom, dist_mm); } static void read_face_data(FILE *file, struct face *f) { float v; if (fscanf(file, "%f", &v) != 1) return; f->z_ref = round(v/f->z_step); if (fscanf(file, "%f", &v) != 1) return; f->fx = tan(v/180*M_PI); if (fscanf(file, "%f", &v) != 1) return; f->fy = tan(v/180*M_PI); if (fscanf(file, "%f", &v) != 1) return; v = v/180*M_PI; f->m.a[0][0] = cos(v); f->m.a[0][1] = -sin(v); f->m.a[1][0] = sin(v); f->m.a[1][1] = cos(v); if (fscanf(file, "%f", &v) != 1) return; f->m.b[0] = v/f->x_step; if (fscanf(file, "%f", &v) != 1) return; f->m.b[1] = v/f->y_step; } static void read_optional(FILE *file, struct project *prj) { float v; if (fscanf(file, "%f", &v) != 1) return; prj->s.dist = v/prj->s.a->z_step; read_face_data(file, prj->s.a); read_face_data(file, prj->s.b); } struct project *load_project(const char *name) { FILE *file; char top[1000], bottom[1000]; /* @@@ enough */ struct project *prj; file = fopen(name, "r"); if (!file) { perror(name); exit(1); } if (!fgets(top, sizeof(top), file)) { fprintf(stderr, "%s: can't read name of top face\n", name); exit(1); } if (strchr(top, '\n')) *strchr(top, '\n') = 0; if (!fgets(bottom, sizeof(bottom), file)) { fprintf(stderr, "%s: can't read name of bottom face\n", bottom); exit(1); } if (strchr(bottom, '\n')) *strchr(bottom, '\n') = 0; prj = make_project(name, top, bottom, 0); read_optional(file, prj); return prj; } static void save_face_data(FILE *file, const char *name, const struct face *f) { double a; a = asin(-f->m.a[0][1])/M_PI*180; if (f->m.a[0][0] < 0) a = 180-a; if (fprintf(file, "%g %g %g\n%g %g %g\n", f->z_ref*f->z_step, atan(f->fx)/M_PI*180, atan(f->fy)/M_PI*180, a, f->m.b[0]*f->x_step, f->m.b[1]*f->y_step) < 0) { perror(name); exit(1); } } void save_project(const struct project *prj) { char tmp[1000]; /* @@@ enough */ FILE *file; sprintf(tmp, "%s~", prj->name); file = fopen(tmp, "w"); if (!file) { perror(tmp); exit(1); } if (fprintf(file, "%s\n%s\n%g\n", prj->top, prj->bottom, prj->s.dist*prj->s.a->z_step) < 0) { perror(tmp); exit(1); } save_face_data(file, tmp, prj->s.a); save_face_data(file, tmp, prj->s.b); if (fclose(file) < 0) { perror(tmp); exit(1); } if (rename(tmp, prj->name) < 0) { fprintf(stderr, "rename %s to %s: %s\n", tmp, prj->name, strerror(errno)); exit(1); } }