1
0
mirror of git://projects.qi-hardware.com/ben-scans.git synced 2024-11-21 21:05:56 +02:00

solidify: fast interactive face to solid converter

This commit is contained in:
Werner Almesberger 2010-09-22 17:04:43 -03:00
parent d5001c6c4a
commit 5f84394774
9 changed files with 371 additions and 0 deletions

13
solidify/Makefile Normal file
View File

@ -0,0 +1,13 @@
CFLAGS=-Wall -g `pkg-config --cflags gtk+-2.0`
LDFLAGS=-lm `pkg-config --libs gtk+-2.0`
OBJS=array.o face.o level.o solidify.o
.PHONY: all clean
all: solidify
solidify: $(OBJS)
clean:
rm -f $(OBJS)

72
solidify/array.c Normal file
View File

@ -0,0 +1,72 @@
#include <stdlib.h>
#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;
}
}

29
solidify/array.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef ARRAY_H
#define ARRAY_H
#include <limits.h>
#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)];
}
#endif /* ARRAY_H */

45
solidify/face.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "util.h"
#include "array.h"
#include "face.h"
struct face *read_face(const char *name)
{
FILE *file;
struct face *f;
float x, y, z;
int xi, yi, zi;
file = strcmp(name, "-") ? fopen(name, "r") : stdin;
if (!file) {
perror(name);
exit(1);
}
f = alloc_type(struct face);
f->a = new_array();
while (fscanf(file, "%f,%f,%f\r\n", &x, &y, &z) == 3) {
/* @@@ hack - should auto-scale */
xi = round(x*10.0);
yi = round(y*10.0);
zi = round(z*40.0);
set(f->a, xi, yi, zi);
}
(void) fclose(file);
f->sx = f->a->max_x-f->a->min_x+1;
f->sy = f->a->max_y-f->a->min_y+1;
f->z_ref = (f->a->min_z+f->a->max_z)/2;
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;
}

16
solidify/face.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef FACE_H
#define FACE_H
#include "array.h"
struct face {
struct array *a;
int sx, sy;
int z_ref;
};
struct face *read_face(const char *name);
#endif /* FACE_H */

139
solidify/level.c Normal file
View File

@ -0,0 +1,139 @@
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include "array.h"
#include "face.h"
#include "level.h"
static void draw_map(GtkWidget *widget, struct face *f)
{
int x, y, z;
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;
}
if (z == f->z_ref) {
*p++ = 0;
*p++ = 0;
*p++ = 255;
continue;
}
if (z < f->z_ref) {
z = 255.0*(z-f->z_ref)/(f->z_ref-f->a->min_z);
*p++ = 255;
*p++ = z;
*p++ = z;
} else {
z = 255.0*(f->z_ref-z)/(f->a->max_z-f->z_ref);
*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 *da, struct face *f)
{
fprintf(stderr, "%d\n", f->z_ref);
draw_map(da, f);
}
static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event,
gpointer data)
{
GtkWidget *da = gtk_bin_get_child(GTK_BIN(widget));
struct face *f = data;
switch (event->direction) {
case GDK_SCROLL_UP:
if (f->z_ref > f->a->min_z) {
f->z_ref--;
draw_image(da, f);
}
break;
case GDK_SCROLL_DOWN:
if (f->z_ref < f->a->max_z) {
f->z_ref++;
draw_image(da, f);
}
break;
default:
/* ignore */;
}
return TRUE;
}
static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event,
gpointer user_data)
{
draw_image(widget, user_data);
return TRUE;
}
static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event,
gpointer data)
{
if (event->keyval == 'q')
gtk_main_quit();
return TRUE;
}
static void make_screen(GtkWidget *root, struct face *f)
{
GtkWidget *evbox, *da;
da = gtk_drawing_area_new();
gtk_widget_set_size_request(da, f->sx, f->sy);
evbox = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(evbox), da);
gtk_container_add(GTK_CONTAINER(root), evbox);
gtk_widget_show_all(root);
draw_map(da, f);
g_signal_connect(G_OBJECT(evbox), "scroll-event",
G_CALLBACK(scroll_event), f);
g_signal_connect(G_OBJECT(da), "expose-event",
G_CALLBACK(expose_event), f);
g_signal_connect(G_OBJECT(root), "key-press-event",
G_CALLBACK(key_press_event), NULL);
}
void level(struct face *f)
{
GtkWidget *root;
root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
#if 0
/* get root->window */
gtk_widget_show_all(root);
#endif
g_signal_connect(G_OBJECT(root), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
make_screen(root, f);
gtk_main();
}

9
solidify/level.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef LEVEL_H
#define LEVEL_H
#include "face.h"
void level(struct face *f);
#endif /* LEVEL_H */

33
solidify/solidify.c Normal file
View File

@ -0,0 +1,33 @@
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#include <gtk/gtk.h>
#include "face.h"
#include "level.h"
static void usage(const char *name)
{
fprintf(stderr, "usage: %s top XXXbottomXXX\n", name);
exit(1);
}
int main(int argc, char **argv)
{
struct face *top;
gtk_init(&argc, &argv);
switch (argc) {
case 2:
break;
default:
usage(*argv);
}
setlocale(LC_ALL, "C"); /* damage control */
top = read_face(argv[1]);
level(top);
return 0;
}

15
solidify/util.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdlib.h>
#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)))
#endif /* UTIL_H */