Date:2010-09-24 03:17:19 (8 years 10 months ago)
Author:Werner Almesberger
Commit:cef7cd5e18edbe511174bc70b0f4043e5cdff74f
Message: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
Files: solidify/Makefile (1 diff)
solidify/array.c (1 diff)
solidify/array.h (1 diff)
solidify/face.c (1 diff)
solidify/face.h (1 diff)
solidify/overlap.c (1 diff)
solidify/overlap.h (1 diff)

Change Details

solidify/Makefile
1212
1313SHELL = /bin/bash
1414
15OBJS = array.o face.o histo.o level.o solidify.o
15OBJS = array.o face.o histo.o level.o overlap.o solidify.o
1616
1717CFLAGS_WARN = -Wall -Wshadow -Wmissing-prototypes \
1818          -Wmissing-declarations -Wno-format-zero-length
1919
20CFLAGS = $(CFLAGS_WARN) -g `pkg-config --cflags gtk+-2.0`
20CFLAGS = $(CFLAGS_WARN) -g -O9 `pkg-config --cflags gtk+-2.0`
2121LDFLAGS = -lm `pkg-config --libs gtk+-2.0`
2222
2323# ----- Verbosity control -----------------------------------------------------
solidify/array.c
8383        a->data[x-a->min_x+(a->max_x-a->min_x+1)*(y-a->min_y)] = z;
8484    }
8585}
86
87
88int get_bounded(const struct array *a, int x, int y)
89{
90    if (x < a->min_x || x > a->max_x)
91        return UNDEF;
92    if (y < a->min_y || y > a->max_y)
93        return UNDEF;
94    return get(a, x, y);
95}
solidify/array.h
3131void free_array(struct array *a);
3232
3333void set(struct array *a, int x, int y, int z);
34int get_bounded(const struct array *a, int x, int y);
3435
3536
3637static inline int get(const struct array *a, int x, int y)
solidify/face.c
7474
7575    f->sx = f->a->max_x-f->a->min_x+1;
7676    f->sy = f->a->max_y-f->a->min_y+1;
77
7778    h = make_histo(f->a);
7879    f->z_ref = f->a->min_z+median(h);
7980    free_histo(h);
8081    f->fx = f->fy = 0;
8182
83    f->m.a[0][0] = f->m.a[1][1] = 1;
84    f->m.a[0][1] = f->m.a[1][0] = 0;
85    f->m.b[0] = f->m.b[1] = 0;
86
8287    fprintf(stderr, "%d-%d / %d-%d / %d-%d\n",
8388        f->a->min_x, f->a->max_x, f->a->min_y, f->a->max_y,
8489        f->a->min_z, f->a->max_z);
solidify/face.h
1616#include "array.h"
1717
1818
19/*
20 * 2D transformation:
21 *
22 * x' = x*a[0][0]+y*a[0][1]+b[0]
23 * y' = x*a[1][0]+y*a[1][1]+b[1]
24 */
25
26
27struct matrix {
28    double a[2][2];
29    double b[2];
30};
31
1932struct face {
2033    struct array *a;
2134    int sx, sy; /* size */
2235    int z_ref;
2336    double fx, fy; /* inclination factor */
37    struct matrix m;
2438};
2539
2640
solidify/overlap.c
1/*
2 * overlap.c - Overlap two parallel faces
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 2010 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stdlib.h>
15#include <stdio.h>
16#include <math.h>
17#include <limits.h>
18#include <gtk/gtk.h>
19
20#include "face.h"
21#include "overlap.h"
22
23
24#define UNDEF_F HUGE_VAL
25
26
27static double ramp(int z0, double w0, int z1, double w1)
28{
29    if (z0 != UNDEF && z1 != UNDEF)
30        return w0 == 0 && w1 == 0 ? z0 : z0*w0+z1*w1;
31    if (z0 == UNDEF && z0 == UNDEF)
32        return UNDEF_F;
33    if (z0 == UNDEF && w0 < w1)
34        return z1;
35    if (z1 == UNDEF && w0 > w1)
36        return z0;
37    return UNDEF_F;
38}
39
40
41static double zmix(struct face *f, double x, double y)
42{
43    int xa, xb, ya, yb;
44    double zx0, zx1;
45
46    xa = floor(x);
47    xb = ceil(x);
48    ya = floor(y);
49    yb = ceil(y);
50
51    zx0 = ramp(
52        get_bounded(f->a, xa, ya), yb-y,
53        get_bounded(f->a, xa, yb), y-ya);
54    zx1 = ramp(
55        get_bounded(f->a, xb, ya), yb-y,
56        get_bounded(f->a, xb, yb), y-ya);
57
58    return ramp(zx0, xb-x, zx1, x-xa);
59}
60
61
62static void draw_image(GtkWidget *widget, struct face *f)
63{
64    guchar *rgbbuf, *p;
65    int x, y;
66    double z;
67
68    rgbbuf = p = calloc(f->sx*f->sy, 3);
69    if (!rgbbuf) {
70        perror("calloc");
71        exit(1);
72    }
73    for (y = f->sy-1; y >= 0; y--)
74        for (x = 0; x != f->sx ; x++) {
75            int xa = x+f->a->min_x;
76            int ya = y+f->a->min_y;
77
78            z = zmix(f,
79                xa*f->m.a[0][0]+ya*f->m.a[0][1]+f->m.b[0],
80                xa*f->m.a[1][0]+ya*f->m.a[1][1]+f->m.b[1]);
81            if (z == UNDEF_F) {
82                p += 3;
83                continue;
84            }
85            z = 256.0*(z-f->a->min_z)/(f->a->max_z-f->a->min_z);
86            if (z < 0)
87                z = 0;
88            if (z > 255)
89                z = 255;
90            *p++ = z;
91            *p++ = z;
92            *p++ = z;
93        }
94    gdk_draw_rgb_image(widget->window,
95        widget->style->fg_gc[GTK_STATE_NORMAL],
96        0, 0, f->sx, f->sy, GDK_RGB_DITHER_MAX, rgbbuf, f->sx*3);
97    free(rgbbuf);
98}
99
100
101/*
102 * Rotate such that a point at distance "r" moves one unit. Rotate
103 * counter-clockwise for r > 1, clockwise for r < 0.
104 */
105
106static void rotate(struct matrix *m, double r)
107{
108    struct matrix t;
109    double s, c;
110
111    s = 1/r;
112    c = sqrt(1-s*s);
113    t.a[0][0] = m->a[0][0]*c-m->a[1][0]*s;
114    t.a[0][1] = m->a[0][1]*c-m->a[1][1]*s;
115    t.a[1][0] = m->a[1][0]*c+m->a[0][0]*s;
116    t.a[1][1] = m->a[1][1]*c+m->a[0][1]*s;
117    t.b[0] = m->b[0]*c-m->b[1]*s;
118    t.b[1] = m->b[0]*s+m->b[1]*c;
119    *m = t;
120}
121
122
123static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event,
124    gpointer data)
125{
126    GtkWidget *da = gtk_bin_get_child(GTK_BIN(widget));
127    struct face *f = data;
128    int dx = event->x-f->sx/2;
129    int dy = event->y-f->sy/2;
130    double r = hypot(dx, dy);
131
132    if (r < 1)
133        return TRUE;
134    switch (event->direction) {
135    case GDK_SCROLL_UP:
136        rotate(&f->m, r);
137        draw_image(da, f);
138        break;
139    case GDK_SCROLL_DOWN:
140        rotate(&f->m, -r);
141        draw_image(da, f);
142        break;
143    default:
144        /* ignore */;
145    }
146    return TRUE;
147}
148
149
150static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event,
151    gpointer user_data)
152{
153    draw_image(widget, user_data);
154    return TRUE;
155}
156
157
158
159static void make_screen(GtkWidget *root, struct face *f)
160{
161    GtkWidget *evbox, *da;
162
163    da = gtk_drawing_area_new();
164    gtk_widget_set_size_request(da, f->sx, f->sy);
165    evbox = gtk_event_box_new();
166    gtk_container_add(GTK_CONTAINER(evbox), da);
167    gtk_container_add(GTK_CONTAINER(root), evbox);
168    gtk_widget_show_all(root);
169    draw_image(da, f);
170
171    g_signal_connect(G_OBJECT(evbox), "scroll-event",
172        G_CALLBACK(scroll_event), f);
173    g_signal_connect(G_OBJECT(da), "expose-event",
174        G_CALLBACK(expose_event), f);
175}
176
177void overlap(struct face *face)
178{
179    GtkWidget *root;
180
181    root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
182    gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
183
184    g_signal_connect(G_OBJECT(root), "destroy",
185        G_CALLBACK(gtk_main_quit), NULL);
186    make_screen(root, face);
187    gtk_main();
188}
solidify/overlap.h
1/*
2 * overlap.h - Overlap two parallel faces
3 *
4 * Written 2010 by Werner Almesberger
5 * Copyright 2010 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#ifndef OVERLAP_H
15#define OVERLAP_H
16
17
18void overlap(struct face *face);
19
20
21#endif /* !OVERLAP_H */

Archive Download the corresponding diff file

Branches:
master



interactive