1 | // |
---|
2 | // "$Id$" |
---|
3 | // |
---|
4 | // Mandelbrot set demo for the Fast Light Tool Kit (FLTK). |
---|
5 | // |
---|
6 | // Copyright 1998-2005 by Bill Spitzak and others. |
---|
7 | // |
---|
8 | // This library is free software; you can redistribute it and/or |
---|
9 | // modify it under the terms of the GNU Library General Public |
---|
10 | // License as published by the Free Software Foundation; either |
---|
11 | // version 2 of the License, or (at your option) any later version. |
---|
12 | // |
---|
13 | // This library is distributed in the hope that it will be useful, |
---|
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
16 | // Library General Public License for more details. |
---|
17 | // |
---|
18 | // You should have received a copy of the GNU Library General Public |
---|
19 | // License along with this library; if not, write to the Free Software |
---|
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
---|
21 | // USA. |
---|
22 | // |
---|
23 | // Please report all bugs and problems on the following page: |
---|
24 | // |
---|
25 | // http://www.fltk.org/str.php |
---|
26 | // |
---|
27 | |
---|
28 | #include "mandelbrot_ui.h" |
---|
29 | #include <FL/fl_draw.H> |
---|
30 | #include <stdio.h> |
---|
31 | #include <stdlib.h> |
---|
32 | |
---|
33 | Drawing_Window mbrot; |
---|
34 | Drawing_Window jbrot; |
---|
35 | |
---|
36 | void idle(void*) { |
---|
37 | if (!mbrot.d->idle() && !(jbrot.d && jbrot.d->idle())) Fl::remove_idle(idle); |
---|
38 | } |
---|
39 | |
---|
40 | void set_idle() { |
---|
41 | Fl::add_idle(idle); |
---|
42 | } |
---|
43 | |
---|
44 | static void window_callback(Fl_Widget*, void*) {exit(0);} |
---|
45 | |
---|
46 | int main(int argc, char **argv) { |
---|
47 | mbrot.make_window(); |
---|
48 | mbrot.d->X = -.75; |
---|
49 | mbrot.d->scale = 2.5; |
---|
50 | mbrot.update_label(); |
---|
51 | int i = 0; |
---|
52 | if (Fl::args(argc,argv,i) < argc) Fl::fatal(Fl::help); |
---|
53 | Fl::visual(FL_RGB); |
---|
54 | mbrot.window->callback(window_callback); |
---|
55 | mbrot.window->show(argc,argv); |
---|
56 | Fl::run(); |
---|
57 | return 0; |
---|
58 | } |
---|
59 | |
---|
60 | void Drawing_Window::update_label() { |
---|
61 | char buffer[128]; |
---|
62 | sprintf(buffer, "%+.10f", d->X); x_input->value(buffer); |
---|
63 | sprintf(buffer, "%+.10f", d->Y); y_input->value(buffer); |
---|
64 | sprintf(buffer, "%.2g", d->scale); w_input->value(buffer); |
---|
65 | } |
---|
66 | |
---|
67 | void Drawing_Area::draw() { |
---|
68 | draw_box(); |
---|
69 | drawn = 0; |
---|
70 | set_idle(); |
---|
71 | } |
---|
72 | |
---|
73 | int Drawing_Area::idle() { |
---|
74 | if (!window()->visible()) return 0; |
---|
75 | if (drawn < nextline) { |
---|
76 | window()->make_current(); |
---|
77 | int yy = drawn+y()+4; |
---|
78 | if (yy >= sy && yy <= sy+sh) erase_box(); |
---|
79 | fl_draw_image_mono(buffer+drawn*W,x()+3,yy,W,1,1,W); |
---|
80 | drawn++; |
---|
81 | return 1; |
---|
82 | } |
---|
83 | if (nextline < H) { |
---|
84 | if (!buffer) buffer = new uchar[W*H]; |
---|
85 | double yy = Y+(H/2-nextline)*scale/W; |
---|
86 | double yi = yy; if (julia) yy = jY; |
---|
87 | uchar *p = buffer+nextline*W; |
---|
88 | for (int xi = 0; xi < W; xi++) { |
---|
89 | double xx = X+(xi-W/2)*scale/W; |
---|
90 | double wx = xx; double wy = yi; |
---|
91 | if (julia) xx = jX; |
---|
92 | for (int i=0; ; i++) { |
---|
93 | if (i >= iterations) {*p = 0; break;} |
---|
94 | double t = wx*wx - wy*wy + xx; |
---|
95 | wy = 2*wx*wy + yy; |
---|
96 | wx = t; |
---|
97 | if (wx*wx + wy*wy > 4) { |
---|
98 | wx = t = 1-double(i)/(1<<10); |
---|
99 | if (t <= 0) t = 0; else for (i=brightness; i--;) t*=wx; |
---|
100 | *p = 255-int(254*t); |
---|
101 | break; |
---|
102 | } |
---|
103 | } |
---|
104 | p++; |
---|
105 | } |
---|
106 | nextline++; |
---|
107 | return nextline < H; |
---|
108 | } |
---|
109 | return 0; |
---|
110 | } |
---|
111 | |
---|
112 | void Drawing_Area::erase_box() { |
---|
113 | window()->make_current(); |
---|
114 | fl_overlay_clear(); |
---|
115 | } |
---|
116 | |
---|
117 | int Drawing_Area::handle(int event) { |
---|
118 | static int ix, iy; |
---|
119 | static int dragged; |
---|
120 | static int button; |
---|
121 | int x2,y2; |
---|
122 | switch (event) { |
---|
123 | case FL_PUSH: |
---|
124 | erase_box(); |
---|
125 | ix = Fl::event_x(); if (ix<x()) ix=x(); if (ix>=x()+w()) ix=x()+w()-1; |
---|
126 | iy = Fl::event_y(); if (iy<y()) iy=y(); if (iy>=y()+h()) iy=y()+h()-1; |
---|
127 | dragged = 0; |
---|
128 | button = Fl::event_button(); |
---|
129 | return 1; |
---|
130 | case FL_DRAG: |
---|
131 | dragged = 1; |
---|
132 | erase_box(); |
---|
133 | x2 = Fl::event_x(); if (x2<x()) x2=x(); if (x2>=x()+w()) x2=x()+w()-1; |
---|
134 | y2 = Fl::event_y(); if (y2<y()) y2=y(); if (y2>=y()+h()) y2=y()+h()-1; |
---|
135 | if (button != 1) {ix = x2; iy = y2; return 1;} |
---|
136 | if (ix < x2) {sx = ix; sw = x2-ix;} else {sx = x2; sw = ix-x2;} |
---|
137 | if (iy < y2) {sy = iy; sh = y2-iy;} else {sy = y2; sh = iy-y2;} |
---|
138 | window()->make_current(); |
---|
139 | fl_overlay_rect(sx,sy,sw,sh); |
---|
140 | return 1; |
---|
141 | case FL_RELEASE: |
---|
142 | if (button == 1) { |
---|
143 | erase_box(); |
---|
144 | if (dragged && sw > 3 && sh > 3) { |
---|
145 | X = X + (sx+sw/2-x()-W/2)*scale/W; |
---|
146 | Y = Y + (-sy-sh/2+y()+H/2)*scale/W; |
---|
147 | scale = sw*scale/W; |
---|
148 | } else if (!dragged) { |
---|
149 | scale = 2*scale; |
---|
150 | if (julia) { |
---|
151 | if (scale >= 4) { |
---|
152 | scale = 4; |
---|
153 | X = Y = 0; |
---|
154 | } |
---|
155 | } else { |
---|
156 | if (scale >= 2.5) { |
---|
157 | scale = 2.5; |
---|
158 | X = -.75; |
---|
159 | Y = 0; |
---|
160 | } |
---|
161 | } |
---|
162 | } else return 1; |
---|
163 | ((Drawing_Window*)(user_data()))->update_label(); |
---|
164 | new_display(); |
---|
165 | } else if (!julia) { |
---|
166 | if (!jbrot.d) { |
---|
167 | jbrot.make_window(); |
---|
168 | jbrot.d->julia = 1; |
---|
169 | jbrot.d->X = 0; |
---|
170 | jbrot.d->Y = 0; |
---|
171 | jbrot.d->scale = 4; |
---|
172 | jbrot.update_label(); |
---|
173 | } |
---|
174 | jbrot.d->jX = X + (ix-x()-W/2)*scale/W; |
---|
175 | jbrot.d->jY = Y + (H/2-iy+y())*scale/W; |
---|
176 | static char s[128]; |
---|
177 | sprintf(s, "Julia %.7f %.7f",jbrot.d->jX,jbrot.d->jY); |
---|
178 | jbrot.window->label(s); |
---|
179 | jbrot.window->show(); |
---|
180 | jbrot.d->new_display(); |
---|
181 | } |
---|
182 | return 1; |
---|
183 | } |
---|
184 | return 0; |
---|
185 | } |
---|
186 | |
---|
187 | void Drawing_Area::new_display() { |
---|
188 | drawn = nextline = 0; |
---|
189 | set_idle(); |
---|
190 | } |
---|
191 | |
---|
192 | void Drawing_Area::resize(int XX,int YY,int WW,int HH) { |
---|
193 | if (WW != w() || HH != h()) { |
---|
194 | W = WW-6; |
---|
195 | H = HH-8; |
---|
196 | if (buffer) {delete[] buffer; buffer = 0; new_display();} |
---|
197 | } |
---|
198 | Fl_Box::resize(XX,YY,WW,HH); |
---|
199 | } |
---|
200 | |
---|
201 | // |
---|
202 | // End of "$Id$". |
---|
203 | // |
---|