diff --git a/solidify/Makefile b/solidify/Makefile deleted file mode 100644 index a36925f..0000000 --- a/solidify/Makefile +++ /dev/null @@ -1,90 +0,0 @@ -# -# Makefile - Makefile of solidify -# -# 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. -# - -SHELL = /bin/bash - -OBJS = array.o face.o histo.o level.o matrix.o overlap.o povray.o project.o \ - solidify.o style.o util.o - -CFLAGS_WARN = -Wall -Wshadow -Wmissing-prototypes \ - -Wmissing-declarations -Wno-format-zero-length - -CFLAGS = $(CFLAGS_WARN) -g -O9 `pkg-config --cflags gtk+-2.0` -LDFLAGS = -lm `pkg-config --libs gtk+-2.0` - -# ----- Verbosity control ----------------------------------------------------- - -CC_normal := $(CC) -DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG - -CC_quiet = @echo " CC " $@ && $(CC_normal) -DEPEND_quiet = @$(DEPEND_normal) - -ifeq ($(V),1) - CC = $(CC_normal) - DEPEND = $(DEPEND_normal) -else - CC = $(CC_quiet) - DEPEND = $(DEPEND_quiet) -endif - -# ----- Rules ----------------------------------------------------------------- - -.PHONY: all clean spotless - -all: solidify - -solidify: $(OBJS) - -clean: - rm -f $(OBJS) $(OBJS:.o=.d) - -spotless: clean - rm -f solidify - -# ----- Experimental execution ------------------------------------------------ - -PRJ=http://projects.qi-hardware.com/index.php/p/ben-scans/source/tree/master -DIR=$(PRJ)/data/csv -FACE_A=$(DIR)/ben-batcvr-outside-100um.txt.bz2 -FACE_B=$(DIR)/ben-batcvr-inside-100um.txt.bz2 -D=1.16 - -.PHONY: new run pov disp - -new: solidify - rm -f batcvr.sfy - ./solidify batcvr.sfy $(FACE_A) $(FACE_B) $(D) >batcvr.inc - -run: solidify - ./solidify batcvr.sfy >batcvr.inc - -pov: - povray +A -W1280 -H1024 main.pov - -disp: - display main.png - -# ----- Dependencies ---------------------------------------------------------- - -# compile and generate dependencies, from fped, based on -# http://scottmcpeak.com/autodepend/autodepend.html - -%.o: %.c - $(CC) -c $(CFLAGS) $*.c -o $*.o - $(DEPEND) $*.c | \ - sed -e \ - '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \ - -e '$${g;p;}' -e d >$*.d; \ - [ "$${PIPESTATUS[*]}" = "0 0" ] || { rm -f $*.d; exit 1; } - --include $(OBJS:.o=.d) diff --git a/solidify/array.c b/solidify/array.c deleted file mode 100644 index d7423e9..0000000 --- a/solidify/array.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * array.c - Growable baseless 2D array - * - * 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 "util.h" -#include "array.h" - - -static void resize(struct array *a, - int nx0, int nx1, int ny0, int ny1) -{ - int ox, oy, nx, ny; - int n, x, y; - int *tmp; - - ox = a->max_x-a->min_x; - oy = a->max_y-a->min_y; - nx = nx1-nx0; - ny = ny1-ny0; - if (ox == nx && oy == ny) - return; - n = (nx+1)*(ny+1); - tmp = alloc_size(n*sizeof(int)); - for (x = 0; x != n; x++) - tmp[x] = UNDEF; - for (x = a->min_x; x <= a->max_x; x++) - for (y = a->min_y; y <= a->max_y; y++) - tmp[x-nx0+(nx+1)*(y-ny0)] = - a->data[x-a->min_x+(ox+1)*(y-a->min_y)]; - free(a->data); - a->data = tmp; - a->min_x = nx0; - a->max_x = nx1; - a->min_y = ny0; - a->max_y = ny1; -} - - -struct array *new_array(void) -{ - struct array *a; - - a = alloc_type(struct array); - a->data = NULL; - return a; -} - - -void free_array(struct array *a) -{ - free(a->data); - free(a); -} - - -void set(struct array *a, int x, int y, int z) -{ - if (!a->data) { - a->min_x = a->max_x = x; - a->min_y = a->max_y = y; - a->min_z = a->max_z = z; - a->data = alloc_type(int); - *a->data = z; - } else { - resize(a, - x < a->min_x ? x : a->min_x, x > a->max_x ? x : a->max_x, - y < a->min_y ? y : a->min_y, y > a->max_y ? y : a->max_y); - if (z < a->min_z) - a->min_z = z; - if (z > a->max_z) - a->max_z = z; - a->data[x-a->min_x+(a->max_x-a->min_x+1)*(y-a->min_y)] = z; - } -} diff --git a/solidify/array.h b/solidify/array.h deleted file mode 100644 index 565e0f8..0000000 --- a/solidify/array.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * array.h - Growable baseless 2D array - * - * 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. - */ - -#ifndef ARRAY_H -#define ARRAY_H - -#include - - -#define UNDEF INT_MAX - - -struct array { - int min_x, max_x; - int min_y, max_y; - int min_z, max_z; - int *data; /* NULL if there are no points */ -}; - - -struct array *new_array(void); -void free_array(struct array *a); - -void set(struct array *a, int x, int y, int z); - - -static inline int get(const struct array *a, int x, int y) -{ - return a->data[(x)-a->min_x+(a->max_x-a->min_x+1)*((y)-a->min_y)]; -} - - -static inline int get_bounded(const struct array *a, int x, int y) -{ - if (x < a->min_x || x > a->max_x) - return UNDEF; - if (y < a->min_y || y > a->max_y) - return UNDEF; - return get(a, x, y); -} - - -#endif /* !ARRAY_H */ diff --git a/solidify/face.c b/solidify/face.c deleted file mode 100644 index d444a14..0000000 --- a/solidify/face.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * 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; -} diff --git a/solidify/face.h b/solidify/face.h deleted file mode 100644 index 46fba86..0000000 --- a/solidify/face.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * face.h - 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. - */ - -#ifndef FACE_H -#define FACE_H - -#include "array.h" -#include "matrix.h" - - -struct face { - struct array *a; - double x_step, y_step, z_step; - int sx, sy; /* size */ - int cx, cy; /* center */ - int z_ref; - double fx, fy; /* inclination factor */ - struct matrix m; -}; - - -static inline double face_z0(const struct face *f, int x, int y) -{ - return f->z_ref+f->fx*(x-f->sx/2)+f->fy*(y-f->sy/2); -} - - -struct face *read_face(const char *name); - -#endif /* !FACE_H */ diff --git a/solidify/histo.c b/solidify/histo.c deleted file mode 100644 index 46f9d92..0000000 --- a/solidify/histo.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * histo.c - Distribution of Z values - * - * 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 "util.h" -#include "array.h" -#include "histo.h" - - -struct histo *make_histo(struct array *a) -{ - int i; - struct histo *h; - - h = alloc_type(struct histo); - h->n = a->max_z-a->min_z+1; - h->b = alloc_size(h->n*sizeof(int)); - for (i = 0; i != h->n; i++) - h->b[i] = 0; - for (i = 0; i != (a->max_x-a->min_x+1)*(a->max_y-a->min_y+1); i++) - if (a->data[i] != UNDEF) - h->b[a->data[i]-a->min_z]++; - return h; -} - - -void free_histo(struct histo *h) -{ - free(h); -} - - -int median(const struct histo *h) -{ - int tot = 0, sum = 0; - int i; - - for (i = 0; i != h->n; i++) - tot += h->b[i]; - for (i = 0; sum < tot/2; i++) - sum += h->b[i]; - return i-1; -} diff --git a/solidify/histo.h b/solidify/histo.h deleted file mode 100644 index 34269d2..0000000 --- a/solidify/histo.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * histo.h - Distribution of Z values - * - * 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. - */ - -#ifndef HISTO_H -#define HISTO_H - -#include "array.h" - - -struct histo { - int n; /* number of bins */ - int *b; /* bins */ -}; - - -struct histo *make_histo(struct array *a); -void free_histo(struct histo *h); -int median(const struct histo *h); - -#endif /* !HISTO_H */ diff --git a/solidify/level.c b/solidify/level.c deleted file mode 100644 index 882253b..0000000 --- a/solidify/level.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * level.c - Interactively align a nearly horizontal plane with a face - * - * 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 "util.h" -#include "array.h" -#include "face.h" -#include "style.h" -#include "level.h" - - -#define NEAR 1 - - -static int has_osd; - - -static double r_center(const struct face *f) -{ - return hypot(f->sx, f->sy)/LEVEL_CENTER_DIV; -} - - -static void draw_map(GtkWidget *widget, struct face *f) -{ - int x, y, z; - double z0; - guchar *rgbbuf, *p; - - rgbbuf = p = calloc(f->sx*f->sy, 3); - if (!rgbbuf) { - perror("calloc"); - exit(1); - } - for (y = f->sy-1; y >= 0; y--) - for (x = 0; x != f->sx ; x++) { - z = get(f->a, x+f->a->min_x, y+f->a->min_y); - if (z == UNDEF) { - p += 3; - continue; - } - z0 = face_z0(f, x, y); - if (fabs(z-z0) < NEAR) { - *p++ = 255*fabs(z-z0); - *p++ = 255*fabs(z-z0); - *p++ = 255; - continue; - } - if (z < z0) { - z = z > z0-2*NEAR ? 255*(z-z0)/NEAR : - 255.0*(z-z0)/(z0-f->a->min_z); - *p++ = 255; - *p++ = z; - *p++ = z; - } else { - z = z < z0+2*NEAR ? 255*(z0-z)/NEAR : - 255.0*(z0-z)/(f->a->max_z-z0); - *p++ = z; - *p++ = 255; - *p++ = z; - } - } - gdk_draw_rgb_image(widget->window, - widget->style->fg_gc[GTK_STATE_NORMAL], - 0, 0, f->sx, f->sy, GDK_RGB_DITHER_MAX, rgbbuf, f->sx*3); - free(rgbbuf); -} - - -static void draw_image(GtkWidget *widget, struct face *f, int osd) -{ - draw_map(widget, f); - has_osd = osd; - if (osd) - draw_circle(widget->window, gc_osd, - f->sx/2, f->sy/2, r_center(f)); -} - - -static void scroll_z(GtkWidget *darea, struct face *f, int up, int osd) -{ - if (up) { - if (f->z_ref < f->a->max_z) - f->z_ref++; - } else { - if (f->z_ref > f->a->min_z) - f->z_ref--; - } - draw_image(darea, f, osd); -} - - -static void scroll_xy(GtkWidget *darea, struct face *f, int dx, int dy, int up, - int osd) -{ - double d; - - d = (double) (up ? 1 : -1)/(dx*dx+dy*dy)/2.0; - f->fx += d*dx; - f->fy += d*dy; - draw_image(darea, f, osd); -} - - -static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, - gpointer data) -{ - GtkWidget *darea = gtk_bin_get_child(GTK_BIN(widget)); - struct face *f = data; - int dx = event->x-f->sx/2; - int dy = event->y-f->sy/2; - double r = hypot(dx, dy); - double rc = r_center(f); - int center = r < rc; - int osd = fabs(r-rc) < OSD_PROXIMITY; - - switch (event->direction) { - case GDK_SCROLL_UP: - if (center) - scroll_z(darea, f, 0, osd); - else - scroll_xy(darea, f, dx, dy, 1, osd); - break; - case GDK_SCROLL_DOWN: - if (center) - scroll_z(darea, f, 1, osd); - else - scroll_xy(darea, f, dx, dy, 0, osd); - break; - default: - /* ignore */; - } - return TRUE; -} - - -static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, - gpointer user_data) -{ - draw_image(widget, user_data, has_osd); - return TRUE; -} - - -static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, - gpointer data) -{ - struct face *f = data; - int dx = event->x-f->sx/2; - int dy = event->y-f->sy/2; - double r = hypot(dx, dy); - double rc = r_center(f); - int osd = fabs(r-rc) < OSD_PROXIMITY; - - if (osd != has_osd) - draw_image(widget, f, osd); - return FALSE; -} - - -void level(GtkWidget *canvas, struct face *f) -{ - GtkWidget *evbox, *darea; - - evbox = gtk_event_box_new(); - darea = gtk_drawing_area_new(); - - gtk_widget_set_events(darea, - GDK_EXPOSE | GDK_KEY_PRESS_MASK | - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_SCROLL | - GDK_POINTER_MOTION_MASK); - - gtk_widget_set_size_request(darea, f->sx, f->sy); - gtk_container_add(GTK_CONTAINER(canvas), evbox); - gtk_container_add(GTK_CONTAINER(evbox), darea); - - draw_image(darea, f, 0); - - g_signal_connect(G_OBJECT(evbox), "scroll-event", - G_CALLBACK(scroll_event), f); - g_signal_connect(G_OBJECT(darea), "expose-event", - G_CALLBACK(expose_event), f); - g_signal_connect(G_OBJECT(darea), "motion-notify-event", - G_CALLBACK(motion_notify_event), f); -} diff --git a/solidify/level.h b/solidify/level.h deleted file mode 100644 index 9a6f7f5..0000000 --- a/solidify/level.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * level.h - Interactively align a nearly horizontal plane with a face - * - * 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. - */ - -#ifndef LEVEL_H -#define LEVEL_H - -#include - -#include "face.h" - - -void level(GtkWidget *canvas, struct face *f); - -#endif /* !LEVEL_H */ diff --git a/solidify/main.pov b/solidify/main.pov deleted file mode 100644 index 44b79e7..0000000 --- a/solidify/main.pov +++ /dev/null @@ -1,51 +0,0 @@ -#include "colors.inc" -#include "batcvr.inc" - -/* - * POV-Ray defaults to a "camera" coordinate system that can be confusing. - * We use a traditional mathematical/engineering view, with a view from - * X-/Y-/Z+ into the X/Y plane. - */ - -camera { - location <-30, -80, 40> - look_at <20, 20, 0> - sky z - right -4/3*x -} - -background { color White } - -light_source { - <-200, -300, 200> - color White -} - -/* - * Mark the coordinate axes: - * - a red unit sphere at the center - * - three green spheres at x = 10*i - * - two blue spheres at y = 10*i - * - one yellow sphere at z = 10 - */ - -sphere { < 0, 0, 0>, 1 pigment { color Red } } -sphere { <10, 0, 0>, 1 pigment { color Green } } -sphere { <20, 0, 0>, 1 pigment { color Green } } -sphere { <30, 0, 0>, 1 pigment { color Green } } -sphere { < 0, 10, 0>, 1 pigment { color Blue } } -sphere { < 0, 20, 0>, 1 pigment { color Blue } } -sphere { < 0, 0, 10>, 1 pigment { color Yellow } } - -#declare Finish = finish { - brilliance 2 - phong 0.8 - phong_size 100 - metallic -} - -union { - Part_batcvr - pigment { rgbf <0.9, 0.9, 0.9, 0.5> } - finish { Finish } -} diff --git a/solidify/matrix.c b/solidify/matrix.c deleted file mode 100644 index 63e90fd..0000000 --- a/solidify/matrix.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * matrix.c - 2D matrix operations - * - * 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 "matrix.h" - - -void matrix_identity(struct matrix *m) -{ - m->a[0][0] = m->a[1][1] = 1; - m->a[0][1] = m->a[1][0] = 0; - m->b[0] = m->b[1] = 0; -} - - -void matrix_invert(const double m[2][2], double res[2][2]) -{ - double det = m[0][0]*m[1][1]-m[0][1]*m[1][0]; - - assert(res != (void *) m); - res[0][0] = m[1][1]/det; - res[0][1] = -m[0][1]/det; - res[1][0] = -m[1][0]/det; - res[1][1] = m[0][0]/det; -} - - -void matrix_mult(double a[2][2], double b[2][2], double res[2][2]) -{ - assert(res != a); - assert(res != b); - res[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]; - res[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]; - res[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]; - res[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]; -} - - -void matrix_multv(const double v[2], double m[2][2], double res[2]) -{ - double tmp; - - tmp = v[0]*m[0][0]+v[1]*m[0][1]; - res[1] = v[0]*m[1][0]+v[1]*m[1][1]; - res[0] = tmp; -} - - -void matrix_copy(double from[2][2], double to[2][2]) -{ - to[0][0] = from[0][0]; - to[0][1] = from[0][1]; - to[1][0] = from[1][0]; - to[1][1] = from[1][1]; -} diff --git a/solidify/matrix.h b/solidify/matrix.h deleted file mode 100644 index 4b83404..0000000 --- a/solidify/matrix.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * matrix.h - 2D matrix operations - * - * 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. - */ - -#ifndef MATRIX_H -#define MATRIX_H - -/* - * 2D transformation: - * - * x' = x*a[0][0]+y*a[0][1]+b[0] - * y' = x*a[1][0]+y*a[1][1]+b[1] - */ - - -struct matrix { - double a[2][2]; - double b[2]; -}; - - -void matrix_identity(struct matrix *m); -void matrix_invert(const double m[2][2], double res[2][2]); -void matrix_mult(double a[2][2], double b[2][2], double res[2][2]); -void matrix_multv(const double v[2], double m[2][2], double res[2]); -void matrix_copy(double from[2][2], double to[2][2]); - - -static inline void matrix_map(int x, int y, const struct matrix *m, - double *res_x, double *res_y) -{ - *res_x = x*m->a[0][0]+y*m->a[0][1]+m->b[0]; - *res_y = x*m->a[1][0]+y*m->a[1][1]+m->b[1]; - -} - -#endif /* !MATRIX_H */ diff --git a/solidify/overlap.c b/solidify/overlap.c deleted file mode 100644 index 4ecec71..0000000 --- a/solidify/overlap.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * overlap.c - Overlap two parallel faces - * - * 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 "style.h" -#include "overlap.h" - - -#define UNDEF_F HUGE_VAL - - -static int has_osd; - - -static int sx(const struct solid *s) -{ - return (s->a->sx > s->b->sx ? s->a->sx : s->b->sx)+2*OVERLAP_BORDER; -} - - -static int sy(const struct solid *s) -{ - return (s->a->sy > s->b->sy ? s->a->sy : s->b->sy)+2*OVERLAP_BORDER; -} - - -static double r_center(const struct solid *s) -{ - return hypot(sx(s), sy(s))/OVERLAP_CENTER_DIV; -} - - -static double ramp(int z0, double w0, int z1, double w1) -{ - if (z0 != UNDEF && z1 != UNDEF) - return z0*w0+z1*w1; - if (z0 == UNDEF && z0 == UNDEF) - return UNDEF_F; - if (z0 == UNDEF && w0 < w1) - return z1; - if (z1 == UNDEF && w0 > w1) - return z0; - return UNDEF_F; -} - - -static double zmix(struct face *f, double x, double y) -{ - int xa, xb, ya, yb; - double zx0, zx1; - - xa = floor(x); - xb = xa+1; - ya = floor(y); - yb = ya+1; - - zx0 = ramp( - get_bounded(f->a, xa, ya), yb-y, - get_bounded(f->a, xa, yb), y-ya); - zx1 = ramp( - get_bounded(f->a, xb, ya), yb-y, - get_bounded(f->a, xb, yb), y-ya); - - return ramp(zx0, xb-x, zx1, x-xa); -} - - -/* - * Coordinate transformations, on the example of the x coordinate: - * - * - the x coordinate runs from 0 to sx(s)-1 - * - since we work relative to the screen center, this becomes x-sx(s)/2 - * This is what we perform the coordinate transform on. - * - our model runs from min_x to max_x. Its center is at cx. - */ - -static void point(const struct solid *s, int x, int y, guchar *p, - const struct matrix *ma, const struct matrix *mb) -{ - double za, zb, z; - double xaf, xbf, yaf, ybf; - - matrix_map(x, y, ma, &xaf, &yaf); - matrix_map(x, y, mb, &xbf, &ybf); - - za = zmix(s->a, xaf, yaf); - zb = zmix(s->b, xbf, ybf); - - if (za == UNDEF_F && zb == UNDEF_F) - return; - - if (za == UNDEF_F) { - z = 128.0*(zb-s->b->a->min_z)/(s->b->a->max_z-s->b->a->min_z); - if (z < 0) - z = 0; - if (z > 255) - z = 255; - p[0] = 255; - p[1] = z; - p[2] = z; - return; - } - if (zb == UNDEF_F) { - z = 128.0*(za-s->a->a->min_z)/(s->a->a->max_z-s->a->a->min_z); - if (z < 0) - z = 0; - if (z > 255) - z = 255; - p[0] = z; - p[1] = 255; - p[2] = z; - return; - } - - z = za; - za -= face_z0(s->a, xaf, yaf); - zb -= face_z0(s->b, xbf, ybf); - - if (za+zb < -s->dist) { - p[0] = 0; - p[1] = 0; - p[2] = 255; - return; - } - - z = 256.0*(z-s->a->a->min_z)/(s->a->a->max_z-s->a->a->min_z); - if (z < 0) - z = 0; - if (z > 255) - z = 255; - p[0] = z; - p[1] = z; - p[2] = z; -} - - -static void merge_matrix(struct matrix *m, const struct solid *s, - const struct face *f) -{ - double tm[2][2], tm2[2][2]; - double tv[2]; - double f_x, f_y; - - /* - * Finally, we convert to model matrix coordinates. - * - * v' = v+c - */ - - m->b[0] += f->cx; - m->b[1] += f->cy; - - /* - * Apply shrinkage caused by rotation out of z0. - * We need to divide by x = cos a. We have f = tan a. - * With sin^2 a + cos^2 a = 1, we get - * - * f = sqrt(1-cos^2 a)/cos a - * = sqrt(1-x^2)/x - * f^2 = 1/x^2-1 - * 1/(f^2+1) = x^2 - * cos a = sqrt(1/(f^2+1)) - */ - - f_x = sqrt(f->fx*f->fx+1); - f_y = sqrt(f->fy*f->fy+1); - - m->a[0][0] *= f_x; - m->a[0][1] *= f_x; - m->b[0] *= f_x; - m->a[1][0] *= f_y; - m->a[1][1] *= f_y; - m->b[1] *= f_y; - - /* - * The transformation matrix f->m describes a transformation of - * (centered) model coordinates. We therefore have to reverse it: - * - * v = v'A+b - * v-b = v'A - * (v-b)A^-1 = v' - * vA^-1-bA^-1 = v' - */ - - matrix_invert(f->m.a, tm); - matrix_multv(f->m.b, tm, tv); - tv[0] = -tv[0]; - tv[1] = -tv[1]; - - /* - * Merge with the transformations we have so far: - * - * v' = vA1+b1 the transformation we have so far - * v'' = v'A2+b2 the transformation we apply - * - * v'' = (vA1+b1)A2+b2 - * v'' = vA1A2+b1A2+b2 - */ - - /* - * So far, the theory. To make it really work, we have to calculate - * v'' = vA1A2+b1+b2 - * duh ?!? - */ - - matrix_mult(m->a, tm, tm2); /* A1A2 */ - matrix_copy(tm2, m->a); -// matrix_multv(m->b, tm, m->b); /* b1A2 */ - m->b[0] += tv[0]; /* b2 */ - m->b[1] += tv[1]; - - /* - * Our input is a screen coordinate, its origin is in a corner so we - * first have to make it center-based: - * - * v' = (v-s/2)A+b - * v' = vA+(b-s/2*A) - */ - - tv[0] = sx(s)/2; - tv[1] = sy(s)/2; - matrix_multv(tv, m->a, tv); - m->b[0] -= tv[0]; - m->b[1] -= tv[1]; -} - - -static void draw_map(GtkWidget *widget, struct solid *s) -{ - guchar *rgbbuf, *p; - int x, y; - struct matrix ma = { - .a = { { 1, 0 }, { 0, 1 } }, - .b = { 0, 0 }, - }; - struct matrix mb = { - .a = { { -1, 0 }, { 0, 1 } }, - .b = { 0, 0 }, - }; - - rgbbuf = p = calloc(sx(s)*sy(s), 3); - if (!rgbbuf) { - perror("calloc"); - exit(1); - } - - merge_matrix(&ma, s, s->a); - merge_matrix(&mb, s, s->b); - - for (y = sy(s)-1; y >= 0; y--) - for (x = 0; x != sx(s) ; x++) { - point(s, x, y, p, &ma, &mb); - p += 3; - } - gdk_draw_rgb_image(widget->window, - widget->style->fg_gc[GTK_STATE_NORMAL], - 0, 0, sx(s), sy(s), GDK_RGB_DITHER_MAX, rgbbuf, sx(s)*3); - free(rgbbuf); -} - - -static void draw_image(GtkWidget *widget, struct solid *s, int osd) -{ - int cx = sx(s)/2; - int cy = sy(s)/2; - int p; - - draw_map(widget, s); - has_osd = osd; - if (!osd) - return; - draw_circle(widget->window, gc_osd, cx, cy, r_center(s)); - p = r_center(s)/sqrt(2); - gdk_draw_line(widget->window, gc_osd, cx-p, cy-p, cx+p, cy+p); - gdk_draw_line(widget->window, gc_osd, cx-p, cy+p, cx+p, cy-p); -} - - -/* - * Rotate such that a point at distance "r" moves one unit. Rotate - * counter-clockwise for r > 1, clockwise for r < 0. - */ - -static void rotate(struct matrix *m, double r) -{ - struct matrix t; - double s, c; - - s = 1/r; - c = sqrt(1-s*s); - t.a[0][0] = m->a[0][0]*c-m->a[1][0]*s; - t.a[0][1] = m->a[0][1]*c-m->a[1][1]*s; - t.a[1][0] = m->a[1][0]*c+m->a[0][0]*s; - t.a[1][1] = m->a[1][1]*c+m->a[0][1]*s; - t.b[0] = m->b[0]*c-m->b[1]*s; - t.b[1] = m->b[0]*s+m->b[1]*c; - *m = t; -} - - -static void do_shift(struct matrix *m, double dx, double dy) -{ - m->b[0] += dx; - m->b[1] += dy; -} - - -static void shift(struct matrix *m, int dx, int dy, double dist) -{ - /* - * Wheeling "up" in each quadrant shifts in the respective direction, - * wheeling "down" in the opposite direction. - * - * No rule without exception: we treat the "down" quadrant like the - * "up" quadrant, because it would be extremely counter-intuitive to - * wheel "up" to move "down". - */ - - if (dx > 0 && dy < dx && dy > -dx) - do_shift(m, dist, 0); - if (dx < 0 && dy < -dx && dy > dx) - do_shift(m, -dist, 0); - if (dy > 0 && dx < dy && dx > -dy) - do_shift(m, 0, dist); - if (dy < 0 && dx < -dy && dx > dy) - do_shift(m, 0, dist); /* exception ! */ -} - - -static int osd_proximity(const struct solid *s, int dx, int dy) -{ - double r = hypot(dx, dy); - double rc = r_center(s); - - if (fabs(r-rc) < OSD_PROXIMITY) - return 1; - if (r > rc) - return 0; - if (abs(abs(dx)-abs(dy)) < OSD_PROXIMITY) - return 1; - return 0; -} - - -static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, - gpointer data) -{ - GtkWidget *darea = gtk_bin_get_child(GTK_BIN(widget)); - struct solid *s = data; - int dx = event->x-sx(s)/2; - int dy = event->y-sy(s)/2; - double r = hypot(dx, dy); - double rc = r_center(s); - double rs, rot, dist; - int center = r < rc; - int osd = osd_proximity(s, dx, dy); - - if (r < 1) - return TRUE; - - /* - * rot goes exponentially from SLOWEST_ROT*rs to FASTEST_ROT for - * r = rc to rs, with rs being half the canvas diagonal. - * - * The values are picked such that we achieve sufficient precision at - * a reasonably large distance from the circle (for accidently entering - * the circle would change the mode) but can also spin quickly, e.g., - * when a 180 degrees rotation is needed. - * - * First, normalize to 0 ... 1 - * Then, we start at exp(0) and end at - * exp(ln(SLOWEST_ROT*rs/FASTEST_ROT))) - */ - rs = hypot(sx(s), sy(s))/2; - rot = (r-rc)/(rs-rc); - rot = SLOWEST_ROT*rs*exp(-rot*log(SLOWEST_ROT*rs/FASTEST_ROT)); - - /* - * dist stays at 1 from 0...rc/DIST_STEPS, then linearly goes up to - * DIST_STEPS from rc/DIST_STEPS...rc - */ - dist = r/rc*DIST_STEPS; - if (dist < 0) - dist = 1; - - switch (event->direction) { - case GDK_SCROLL_UP: - if (center) - shift(&s->a->m, dx, dy, dist); - else - rotate(&s->a->m, dx > 0 ? rot : -rot); - draw_image(darea, s, osd); - break; - case GDK_SCROLL_DOWN: - if (center) - shift(&s->a->m, dx, dy, -dist); - else - rotate(&s->a->m, dx > 0 ? -rot : rot); - draw_image(darea, s, osd); - break; - default: - /* ignore */; - } - return TRUE; -} - - -static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, - gpointer user_data) -{ - draw_image(widget, user_data, has_osd); - return TRUE; -} - - -static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, - gpointer data) -{ - struct solid *s = data; - int dx = event->x-sx(s)/2; - int dy = event->y-sy(s)/2; - int osd = osd_proximity(s, dx, dy); - - if (osd != has_osd) - draw_image(widget, s, osd); - return FALSE; -} - - -void overlap(GtkWidget *canvas, struct solid *s) -{ - GtkWidget *evbox, *darea; - - evbox = gtk_event_box_new(); - darea = gtk_drawing_area_new(); - - gtk_widget_set_events(darea, - GDK_EXPOSE | GDK_KEY_PRESS_MASK | - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_SCROLL | - GDK_POINTER_MOTION_MASK); - - gtk_widget_set_size_request(darea, sx(s), sy(s)); - gtk_container_add(GTK_CONTAINER(canvas), evbox); - gtk_container_add(GTK_CONTAINER(evbox), darea); - - draw_image(darea, s, 0); - - g_signal_connect(G_OBJECT(evbox), "scroll-event", - G_CALLBACK(scroll_event), s); - g_signal_connect(G_OBJECT(darea), "expose-event", - G_CALLBACK(expose_event), s); - g_signal_connect(G_OBJECT(darea), "motion-notify-event", - G_CALLBACK(motion_notify_event), s); - -if (0) { -int i; -long t0 = time(NULL); -gtk_widget_show_all(canvas); -for (i = 0; i != 1000; i++) { - rotate(&s->a->m, 100); - draw_image(darea, s, 0); - while (gtk_events_pending()) - gtk_main_iteration(); -} -fprintf(stderr, "%lu\n", time(NULL)-t0); -} - -} diff --git a/solidify/overlap.h b/solidify/overlap.h deleted file mode 100644 index f21bd79..0000000 --- a/solidify/overlap.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * overlap.h - Overlap two parallel faces - * - * 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. - */ - -#ifndef OVERLAP_H -#define OVERLAP_H - -#include - -#include "solid.h" - - -void overlap(GtkWidget *canvas, struct solid *solid); - -#endif /* !OVERLAP_H */ diff --git a/solidify/povray.c b/solidify/povray.c deleted file mode 100644 index b31b853..0000000 --- a/solidify/povray.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * povray.c - Generate POV-Ray output - * - * 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 "face.h" -#include "solid.h" - - -static void height_field(const char *name, const struct face *f, - const struct matrix *m) -{ - FILE *file; - int x, y; - int z; - uint16_t g; - uint8_t v[2]; - - file = fopen(name, "w"); - if (!file) { - perror(name); - exit(1); - } - fprintf(file, "P5\n%d %d\n65535\n", f->sx, f->sy); - for (y = 0; y != f->sy; y++) - for (x = 0; x != f->sx; x++) { - z = get(f->a, x+f->a->min_x, y+f->a->min_y); - g = z == UNDEF ? 0 : - 65535*(z-f->a->min_z)/(f->a->max_z-f->a->min_z); - v[0] = g >> 8; - v[1] = g; - fwrite(v, 2, 1, file); - } - fclose(file); -} - - -static void sanitize(const char *s, char *res) -{ - while (*s) { - if ((*s >= 'A' && *s <= 'Z') || - (*s >= 'a' && *s <= 'z') || - (*s >= '0' && *s <= '9') || *s == '_') - *res = *s; - else - *res = '_'; - res++; - s++; - } - *res = 0; -} - - -/* - * For now, we put the part such that its x/y/z center is at the origin. - * Later, we will also have to consider the changes the user made and the - * relation with the opposing face. - */ - -static void povray_face(const struct face *f, const char *side, - const char *prefix, int flip, double dist) -{ - int sz = f->a->max_z-f->a->min_z; - - /* - * 1/65535 = 0.000015..., so we set the water level a bit lower, e.g., - * to 0.0001 - */ - printf( -"\theight_field {\n" -"\t pgm \"%s-%s.pgm\"\n" -"\t water_level 0.00001\n" -"\t smooth\n" -"\t scale <%g, %g, %g>\n" -"\t rotate <90, 0, 0>\n" -"\t translate <%g, %g, %g>\n" -"\t translate <0, 0, %g>\n" -"%s" /* flip bottom face */ -"\t translate <0, 0, %g>\n" -"\t}\n", prefix, side, - f->sx*f->x_step, sz*f->z_step, f->sy*f->y_step, - -f->sx*f->x_step/2, f->sy*f->y_step/2, f->a->min_z*f->z_step, - -f->z_ref*f->z_step, - flip ? "\t rotate <180, 0, 0>\n" : "", - dist*f->z_step); -} - - -void povray(const char *name, const struct solid *s) -{ - struct matrix m; - char tmp[1000]; /* @@@ enough */ - - m.a[0][0] = m.a[1][1] = 1; - m.a[0][1] = m.a[1][0] = 0; - m.b[0] = m.b[1] = 0; - - sprintf(tmp, "%s-top.pgm", name); - height_field(tmp, s->a, &m); - sprintf(tmp, "%s-bot.pgm", name); - height_field(tmp, s->b, &m); - - sanitize(name, tmp); - printf("#declare Part_%s =\n intersection {\n", tmp); - povray_face(s->a, "top", name, 0, s->dist/2); - povray_face(s->b, "bot", name, 1, -s->dist/2); - printf(" }\n"); -} diff --git a/solidify/project.c b/solidify/project.c deleted file mode 100644 index 792d3fc..0000000 --- a/solidify/project.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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 = 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); - } -} diff --git a/solidify/project.h b/solidify/project.h deleted file mode 100644 index cf7b502..0000000 --- a/solidify/project.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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/solid.h b/solidify/solid.h deleted file mode 100644 index 06a4ba8..0000000 --- a/solidify/solid.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * solid.h - Data structure and handling of a solid made of two opposing faces - * - * 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. - */ - -#ifndef SOLID_H -#define SOLID_H - -struct solid { - struct face *a, *b; - double dist; -}; - - -void povray(const char *name, const struct solid *s); - -#endif /* !SOLID_H */ diff --git a/solidify/solidify.c b/solidify/solidify.c deleted file mode 100644 index 0fc41f7..0000000 --- a/solidify/solidify.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * solidify.c - Merge two opposing faces of a part into a solid - * - * Written 2010 by Werner Almesberger - * Copyright 2010 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 "face.h" -#include "solid.h" -#include "project.h" -#include "style.h" -#include "level.h" -#include "overlap.h" - - -static struct project *prj; -static const struct face *active; /* NULL if overlapping */ -static GtkWidget *canvas; - - -static void clicked(GtkButton *button, gpointer user_data) -{ - struct face *face = user_data; - - if (active == face) - return; - - gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(canvas))); - - if (face) - level(canvas, face); - else - overlap(canvas, &prj->s); - active = face; - - gtk_widget_show_all(canvas); -} - - -static GtkWidget *gui_buttons(void) -{ - GtkWidget *vbox, *but; - - vbox = gtk_vbox_new(FALSE, 0); - - 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), 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), prj->s.b); - - but = gtk_button_new_with_label("A+B"); - gtk_box_pack_start(GTK_BOX(vbox), but, FALSE, FALSE, 0); - g_signal_connect(G_OBJECT(but), "clicked", - G_CALLBACK(clicked), NULL); - - return vbox; -} - - -static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, - gpointer data) -{ - if (event->keyval == 'q') - gtk_main_quit(); - return TRUE; -} - - -static void gui(void) -{ - GtkWidget *root, *hbox, *buttons; - - root = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER); - - hbox = gtk_hbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(root), hbox); - - canvas = gtk_event_box_new(); - gtk_box_pack_start(GTK_BOX(hbox), canvas, FALSE, FALSE, 0); - - /* initialize root->window */ - gtk_widget_show_all(root); - - buttons = gui_buttons(); - gtk_box_pack_start(GTK_BOX(hbox), buttons, FALSE, FALSE, 0); - - level(canvas, prj->s.a); - active = prj->s.a; - - init_style(root->window); - - gtk_widget_show_all(root); - - g_signal_connect(G_OBJECT(root), "key-press-event", - G_CALLBACK(key_press_event), NULL); - g_signal_connect(G_OBJECT(root), "destroy", - G_CALLBACK(gtk_main_quit), NULL); - - gtk_main(); -} - - -static void usage(const char *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 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); - } - - gui(); - - save_project(prj); - - if (!isatty(1)) { - const char *slash = strrchr(prj->name, '/'); - char tmp[1000]; /* @@@ enough */ - - strcpy(tmp, slash ? slash+1 : prj->name); - if (strchr(tmp, '.')) - *strchr(tmp, '.') = 0; - povray(tmp, &prj->s); - } - - return 0; -} diff --git a/solidify/style.c b/solidify/style.c deleted file mode 100644 index 6b260a8..0000000 --- a/solidify/style.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * style.c - GUI style parameters and items - * - * 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 "style.h" - - -GdkGC *gc_osd; - - -static GdkColor get_color(GdkDrawable *da, const char *spec) -{ - GdkColormap *cmap; - GdkColor color; - - cmap = gdk_drawable_get_colormap(da); - if (!gdk_color_parse(spec, &color)) - abort(); - if (!gdk_colormap_alloc_color(cmap, &color, FALSE, TRUE)) - abort(); - return color; -} - - -static GdkGC *gc(GdkDrawable *da, const char *spec, int width) -{ - GdkGCValues gc_values = { - .background = get_color(da, "black"), - .foreground = get_color(da, spec), - .line_width = width, - }; - - return gdk_gc_new_with_values(da, &gc_values, - GDK_GC_FOREGROUND | GDK_GC_BACKGROUND | GDK_GC_LINE_WIDTH); -} - - -void init_style(GdkDrawable *da) -{ - gc_osd = gc(da, "#ffff00", 4); -} diff --git a/solidify/style.h b/solidify/style.h deleted file mode 100644 index 39085fb..0000000 --- a/solidify/style.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * style.h - GUI style parameters and items - * - * 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. - */ - -#ifndef STYLE_H -#define STYLE_H - -#include - - -extern GdkGC *gc_osd; - - -#define OSD_PROXIMITY 20 /* pixels */ -#define LEVEL_CENTER_DIV 5 /* fraction of diagonal */ -#define OVERLAP_BORDER 10 /* pixels around min. drawing area */ -#define OVERLAP_CENTER_DIV 5 /* fraction of diagonal */ -#define SLOWEST_ROT 3 /* thrice the half-diagonal */ -#define FASTEST_ROT 2 /* one pixel in distance of 2 pixels */ -#define DIST_STEPS 5 /* fastest shift is 5 px/wheel step */ - - -void init_style(GdkDrawable *da); - -#endif /* !STYLE_H */ diff --git a/solidify/util.c b/solidify/util.c deleted file mode 100644 index 40206d1..0000000 --- a/solidify/util.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * util.c - Common utility functions - * - * 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 "util.h" - - -void draw_circle(GdkDrawable *da, GdkGC *gc, int x, int y, int r) -{ - gdk_draw_arc(da, gc, FALSE, x-r, y-r, 2*r, 2*r, 0, 360*64); -} diff --git a/solidify/util.h b/solidify/util.h deleted file mode 100644 index 635f258..0000000 --- a/solidify/util.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * util.h - Common utility functions - * - * Written 2009 by Werner Almesberger - * Copyright 2009 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. - */ - -#ifndef UTIL_H -#define UTIL_H - -#include -#include -#include - - -#define alloc_size(s) \ - ({ void *alloc_size_tmp = malloc(s); \ - if (!alloc_size_tmp) \ - abort(); \ - alloc_size_tmp; }) - -#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); - -#endif /* !UTIL_H */