diff --git a/solidify/Makefile b/solidify/Makefile index 5111edc..f2072ed 100644 --- a/solidify/Makefile +++ b/solidify/Makefile @@ -12,8 +12,8 @@ SHELL = /bin/bash -OBJS = array.o face.o histo.o level.o matrix.o overlap.o solid.o solidify.o \ - style.o util.o +OBJS = array.o face.o histo.o level.o matrix.o overlap.o project.o solid.o \ + solidify.o style.o util.o CFLAGS_WARN = -Wall -Wshadow -Wmissing-prototypes \ -Wmissing-declarations -Wno-format-zero-length @@ -59,10 +59,14 @@ FACE_A=$(DIR)/ben-batcvr-outside-100um.txt.bz2 FACE_B=$(DIR)/ben-batcvr-inside-100um.txt.bz2 D=1.16 -.PHONY: run pov disp +.PHONY: new run pov disp + +new: solidify + rm -f batcvr.sfy + ./solidify batcvr.sfy $(FACE_A) $(FACE_B) $(D) >batcvr.inc run: solidify - ./solidify $(FACE_A) $(FACE_B) $(D) >batcvr.inc + ./solidify batcvr.sfy >batcvr.inc pov: povray +A -W1280 -H1024 main.pov diff --git a/solidify/project.c b/solidify/project.c new file mode 100644 index 0000000..2f803b8 --- /dev/null +++ b/solidify/project.c @@ -0,0 +1,192 @@ +/* + * 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 = v/f->z_step; + + if (fscanf(file, "%f", &v) != 1) + return; + f->fx = sin(v/180*M_PI); + + if (fscanf(file, "%f", &v) != 1) + return; + f->fy = sin(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, + asin(f->fx)/M_PI*180, asin(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); + } +} diff --git a/solidify/project.h b/solidify/project.h new file mode 100644 index 0000000..cf7b502 --- /dev/null +++ b/solidify/project.h @@ -0,0 +1,48 @@ +/* + * project.h - 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. + */ + +/* + * Project file structure: + * + * line 1: file name of top face (required) + * line 2: file name of bottom face (required) + * line 3 and beyond, separated by whitespace: + * - z distance between faces, in mm + * - z distance of the z0 plane from the midpoint of the top face, in mm + * - inclination of the x axis of the z0 plane of the top face, in degrees + * - inclination of the y axis of the z0 plane of the top face, in degrees + * - rotation of the top face, in degrees + * - x shift of the top face, in mm + * - y shift of the top face, in mm + * - the above 6 fields for the bottom face + */ + +#ifndef PROJECT_H +#define PROJECT_H + +#include "solid.h" + + +struct project { + const char *name; + const char *top; + const char *bottom; + struct solid s; +}; + + +struct project *new_project(const char *name, + const char *top, const char *bottom, double dist_mm); +struct project *load_project(const char *name); +void save_project(const struct project *prj); + +#endif /* !PROJECT_H */ diff --git a/solidify/solidify.c b/solidify/solidify.c index 871abd1..413fe44 100644 --- a/solidify/solidify.c +++ b/solidify/solidify.c @@ -19,13 +19,14 @@ #include "face.h" #include "solid.h" +#include "project.h" #include "style.h" #include "level.h" #include "overlap.h" -static struct solid solid; -static const struct face *active; +static struct project *prj; +static const struct face *active; /* NULL if overlapping */ static GtkWidget *canvas; @@ -41,7 +42,7 @@ static void clicked(GtkButton *button, gpointer user_data) if (face) level(canvas, face); else - overlap(canvas, &solid); + overlap(canvas, &prj->s); active = face; gtk_widget_show_all(canvas); @@ -57,12 +58,12 @@ static GtkWidget *gui_buttons(void) but = gtk_button_new_with_label("A"); gtk_box_pack_start(GTK_BOX(vbox), but, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(but), "clicked", - G_CALLBACK(clicked), solid.a); + G_CALLBACK(clicked), prj->s.a); but = gtk_button_new_with_label("B"); gtk_box_pack_start(GTK_BOX(vbox), but, FALSE, FALSE, 0); g_signal_connect(G_OBJECT(but), "clicked", - G_CALLBACK(clicked), solid.b); + G_CALLBACK(clicked), prj->s.b); but = gtk_button_new_with_label("A+B"); gtk_box_pack_start(GTK_BOX(vbox), but, FALSE, FALSE, 0); @@ -101,8 +102,8 @@ static void gui(void) buttons = gui_buttons(); gtk_box_pack_start(GTK_BOX(hbox), buttons, FALSE, FALSE, 0); - level(canvas, solid.a); - active = solid.a; + level(canvas, prj->s.a); + active = prj->s.a; init_style(root->window); @@ -119,37 +120,36 @@ static void gui(void) static void usage(const char *name) { - fprintf(stderr, "usage: %s top bottom dist\n", name); + fprintf(stderr, "usage: %s project [top bottom dist]\n", name); exit(1); } int main(int argc, char **argv) { + double dist; + gtk_init(&argc, &argv); setlocale(LC_ALL, "C"); /* damage control */ switch (argc) { - case 4: + case 2: + prj = load_project(argv[1]); + break; + case 5: + dist = atof(argv[4]); + prj = new_project(argv[1], argv[2], argv[3], dist); break; default: usage(*argv); } - solid.a = read_face(argv[1]); - solid.b = read_face(argv[2]); - if (solid.a->x_step != solid.a->x_step || - solid.a->y_step != solid.a->y_step || - solid.a->z_step != solid.a->z_step) { - fprintf(stderr, "both faces must have the same resolution\n"); - exit(1); - } - solid.dist = atof(argv[3])/solid.a->z_step; - gui(); + save_project(prj); + if (!isatty(1)) - povray(&solid); + povray(&prj->s); return 0; } diff --git a/solidify/util.h b/solidify/util.h index 933bb96..635f258 100644 --- a/solidify/util.h +++ b/solidify/util.h @@ -14,6 +14,7 @@ #define UTIL_H #include +#include #include @@ -25,6 +26,12 @@ #define alloc_type(t) ((t *) alloc_size(sizeof(t))) +#define stralloc(s) \ + ({ char *stralloc_tmp = strdup(s); \ + if (!stralloc_tmp) \ + abort(); \ + stralloc_tmp; }) + void draw_circle(GdkDrawable *da, GdkGC *gc, int x, int y, int r);