mirror of
git://projects.qi-hardware.com/ben-scans.git
synced 2024-11-22 03:14:39 +02:00
Added interactive 2D transformation (working towards overlapping)
- solidify/Makefile (OBJS): added overlap.o - solidify/Makefile (CFLAGS): added -O9 to speed up rotation a little - solidify/array.h, solidify/array.c (get_bounded): like get(), but returns UNDEF if the indices are outside the array - solidify/face.h (struct face, struct matrix), solidify/face.c (read_file): added a 2D transformation matrix to "struct face" - solidify/overlap.h, solidify/overlap.c: show a face with 2D transformation
This commit is contained in:
parent
598df91d9f
commit
cef7cd5e18
@ -12,12 +12,12 @@
|
||||
|
||||
SHELL = /bin/bash
|
||||
|
||||
OBJS = array.o face.o histo.o level.o solidify.o
|
||||
OBJS = array.o face.o histo.o level.o overlap.o solidify.o
|
||||
|
||||
CFLAGS_WARN = -Wall -Wshadow -Wmissing-prototypes \
|
||||
-Wmissing-declarations -Wno-format-zero-length
|
||||
|
||||
CFLAGS = $(CFLAGS_WARN) -g `pkg-config --cflags gtk+-2.0`
|
||||
CFLAGS = $(CFLAGS_WARN) -g -O9 `pkg-config --cflags gtk+-2.0`
|
||||
LDFLAGS = -lm `pkg-config --libs gtk+-2.0`
|
||||
|
||||
# ----- Verbosity control -----------------------------------------------------
|
||||
|
@ -83,3 +83,13 @@ void set(struct array *a, int x, int y, int z)
|
||||
a->data[x-a->min_x+(a->max_x-a->min_x+1)*(y-a->min_y)] = z;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ struct array *new_array(void);
|
||||
void free_array(struct array *a);
|
||||
|
||||
void set(struct array *a, int x, int y, int z);
|
||||
int get_bounded(const struct array *a, int x, int y);
|
||||
|
||||
|
||||
static inline int get(const struct array *a, int x, int y)
|
||||
|
@ -74,11 +74,16 @@ static struct face *read_file(const char *name)
|
||||
|
||||
f->sx = f->a->max_x-f->a->min_x+1;
|
||||
f->sy = f->a->max_y-f->a->min_y+1;
|
||||
|
||||
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, "%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);
|
||||
|
@ -16,11 +16,25 @@
|
||||
#include "array.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];
|
||||
};
|
||||
|
||||
struct face {
|
||||
struct array *a;
|
||||
int sx, sy; /* size */
|
||||
int z_ref;
|
||||
double fx, fy; /* inclination factor */
|
||||
struct matrix m;
|
||||
};
|
||||
|
||||
|
||||
|
188
solidify/overlap.c
Normal file
188
solidify/overlap.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "face.h"
|
||||
#include "overlap.h"
|
||||
|
||||
|
||||
#define UNDEF_F HUGE_VAL
|
||||
|
||||
|
||||
static double ramp(int z0, double w0, int z1, double w1)
|
||||
{
|
||||
if (z0 != UNDEF && z1 != UNDEF)
|
||||
return w0 == 0 && w1 == 0 ? z0 : 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 = ceil(x);
|
||||
ya = floor(y);
|
||||
yb = ceil(y);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void draw_image(GtkWidget *widget, struct face *f)
|
||||
{
|
||||
guchar *rgbbuf, *p;
|
||||
int x, y;
|
||||
double z;
|
||||
|
||||
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++) {
|
||||
int xa = x+f->a->min_x;
|
||||
int ya = y+f->a->min_y;
|
||||
|
||||
z = zmix(f,
|
||||
xa*f->m.a[0][0]+ya*f->m.a[0][1]+f->m.b[0],
|
||||
xa*f->m.a[1][0]+ya*f->m.a[1][1]+f->m.b[1]);
|
||||
if (z == UNDEF_F) {
|
||||
p += 3;
|
||||
continue;
|
||||
}
|
||||
z = 256.0*(z-f->a->min_z)/(f->a->max_z-f->a->min_z);
|
||||
if (z < 0)
|
||||
z = 0;
|
||||
if (z > 255)
|
||||
z = 255;
|
||||
*p++ = z;
|
||||
*p++ = z;
|
||||
*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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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 gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *da = 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);
|
||||
|
||||
if (r < 1)
|
||||
return TRUE;
|
||||
switch (event->direction) {
|
||||
case GDK_SCROLL_UP:
|
||||
rotate(&f->m, r);
|
||||
draw_image(da, f);
|
||||
break;
|
||||
case GDK_SCROLL_DOWN:
|
||||
rotate(&f->m, -r);
|
||||
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 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_image(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);
|
||||
}
|
||||
|
||||
void overlap(struct face *face)
|
||||
{
|
||||
GtkWidget *root;
|
||||
|
||||
root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
|
||||
|
||||
g_signal_connect(G_OBJECT(root), "destroy",
|
||||
G_CALLBACK(gtk_main_quit), NULL);
|
||||
make_screen(root, face);
|
||||
gtk_main();
|
||||
}
|
21
solidify/overlap.h
Normal file
21
solidify/overlap.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
||||
void overlap(struct face *face);
|
||||
|
||||
|
||||
#endif /* !OVERLAP_H */
|
Loading…
Reference in New Issue
Block a user