Root/solidify/level.c

Source at commit 525e1557ec1a8e924b25a86c1efe61c93da21179 created 8 years 11 months ago.
By Werner Almesberger, Use two faces and show how they overlap (in progress)
1/*
2 * level.c - Interactively align a nearly horizontal plane with a face
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 <gtk/gtk.h>
18
19#include "array.h"
20#include "face.h"
21#include "level.h"
22
23
24#define NEAR 1
25
26
27static void draw_image(GtkWidget *widget, struct face *f)
28{
29    int x, y, z;
30    double z0;
31    guchar *rgbbuf, *p;
32
33    rgbbuf = p = calloc(f->sx*f->sy, 3);
34    if (!rgbbuf) {
35        perror("calloc");
36        exit(1);
37    }
38    for (y = f->sy-1; y >= 0; y--)
39        for (x = 0; x != f->sx ; x++) {
40            z = get(f->a, x+f->a->min_x, y+f->a->min_y);
41            if (z == UNDEF) {
42                p += 3;
43                continue;
44            }
45            z0 = face_z0(f, x, y);
46            if (fabs(z-z0) < NEAR) {
47                *p++ = 255*fabs(z-z0);
48                *p++ = 255*fabs(z-z0);
49                *p++ = 255;
50                continue;
51            }
52            if (z < z0) {
53                z = z > z0-2*NEAR ? 255*(z-z0)/NEAR :
54                    255.0*(z-z0)/(z0-f->a->min_z);
55                *p++ = 255;
56                *p++ = z;
57                *p++ = z;
58            } else {
59                z = z < z0+2*NEAR ? 255*(z0-z)/NEAR :
60                    255.0*(z0-z)/(f->a->max_z-z0);
61                *p++ = z;
62                *p++ = 255;
63                *p++ = z;
64            }
65        }
66    gdk_draw_rgb_image(widget->window,
67        widget->style->fg_gc[GTK_STATE_NORMAL],
68        0, 0, f->sx, f->sy, GDK_RGB_DITHER_MAX, rgbbuf, f->sx*3);
69    free(rgbbuf);
70}
71
72
73static void scroll_z(GtkWidget *da, struct face *f, int up)
74{
75    if (up) {
76        if (f->z_ref < f->a->max_z)
77            f->z_ref++;
78    } else {
79        if (f->z_ref > f->a->min_z)
80            f->z_ref--;
81    }
82    draw_image(da, f);
83}
84
85
86static void scroll_xy(GtkWidget *da, struct face *f, int dx, int dy, int up)
87{
88    double d;
89
90    d = (double) (up ? 1 : -1)/(dx*dx+dy*dy)/2.0;
91    f->fx += d*dx;
92    f->fy += d*dy;
93    draw_image(da, f);
94}
95
96
97static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event,
98    gpointer data)
99{
100    GtkWidget *da = gtk_bin_get_child(GTK_BIN(widget));
101    struct face *f = data;
102    int dx = event->x-f->sx/2;
103    int dy = event->y-f->sy/2;
104    int center = hypot(dx, dy)/hypot(f->sx, f->sy) < 0.25;
105
106    switch (event->direction) {
107    case GDK_SCROLL_UP:
108        if (center)
109            scroll_z(da, f, 0);
110        else
111            scroll_xy(da, f, dx, dy, 1);
112        break;
113    case GDK_SCROLL_DOWN:
114        if (center)
115            scroll_z(da, f, 1);
116        else
117            scroll_xy(da, f, dx, dy, 0);
118        break;
119    default:
120        /* ignore */;
121    }
122    return TRUE;
123}
124
125
126static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event,
127    gpointer user_data)
128{
129    draw_image(widget, user_data);
130    return TRUE;
131}
132
133
134void level(GtkWidget *canvas, struct face *f)
135{
136    GtkWidget *evbox, *da;
137
138    evbox = gtk_event_box_new();
139    da = gtk_drawing_area_new();
140    gtk_widget_set_size_request(da, f->sx, f->sy);
141    gtk_container_add(GTK_CONTAINER(canvas), evbox);
142    gtk_container_add(GTK_CONTAINER(evbox), da);
143
144    draw_image(da, f);
145
146    g_signal_connect(G_OBJECT(evbox), "scroll-event",
147        G_CALLBACK(scroll_event), f);
148    g_signal_connect(G_OBJECT(da), "expose-event",
149        G_CALLBACK(expose_event), f);
150}
151

Archive Download this file

Branches:
master



interactive