fltk/test/mandelbrot.cxx
Michael R Sweet f9039b2ae2 Initial revision
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
1998-10-06 18:21:25 +00:00

201 lines
4.7 KiB
C++

#include "mandelbrot_ui.C"
#include <FL/fl_draw.H>
#include <stdio.h>
#include <stdlib.h>
Drawing_Window mbrot;
Drawing_Window jbrot;
void idle() {
if (!mbrot.d->idle() && !(jbrot.d && jbrot.d->idle())) Fl::set_idle(0);
}
void set_idle() {
Fl::set_idle(idle);
}
static void window_callback(Fl_Widget*, void*) {exit(0);}
int main(int argc, char **argv) {
make_window(mbrot);
mbrot.d->X = -.75;
mbrot.d->scale = 2.5;
mbrot.update_label();
int i = 0;
if (Fl::args(argc,argv,i) < argc) Fl::fatal(Fl::help);
Fl::visual(FL_RGB);
mbrot.window->callback(window_callback);
mbrot.window->show(argc,argv);
Fl::run();
return 0;
}
void Drawing_Window::update_label() {
char buffer[128];
sprintf(buffer, "%+.10f", d->X); x_input->value(buffer);
sprintf(buffer, "%+.10f", d->Y); y_input->value(buffer);
sprintf(buffer, "%.2g", d->scale); w_input->value(buffer);
}
void Drawing_Area::draw() {
draw_box();
drawn = 0;
set_idle();
}
int Drawing_Area::idle() {
if (!window()->visible()) return 0;
if (drawn < nextline) {
window()->make_current();
int yy = drawn+y()+4;
if (yy >= sy && yy <= sy+sh) erase_box();
fl_draw_image_mono(buffer+drawn*W,x()+3,yy,W,1,1,W);
drawn++;
return 1;
}
if (nextline < H) {
if (!buffer) buffer = new uchar[W*H];
double yy = Y+(H/2-nextline)*scale/W;
double yi = yy; if (julia) yy = jY;
uchar *p = buffer+nextline*W;
for (int xi = 0; xi < W; xi++) {
double xx = X+(xi-W/2)*scale/W;
double wx = xx; double wy = yi;
if (julia) xx = jX;
for (int i=0; ; i++) {
if (i >= iterations) {*p = 0; break;}
double t = wx*wx - wy*wy + xx;
wy = 2*wx*wy + yy;
wx = t;
if (wx*wx + wy*wy > 4) {
wx = t = 1-double(i)/(1<<10);
if (t <= 0) t = 0; else for (i=brightness; i--;) t*=wx;
*p = 255-int(254*t);
break;
}
}
p++;
}
nextline++;
return nextline < H;
}
return 0;
}
void Drawing_Area::erase_box() {
window()->make_current();
fl_overlay_clear();
}
int Drawing_Area::handle(int event) {
static int ix, iy;
static int dragged;
static int button;
int x2,y2;
switch (event) {
case FL_PUSH:
erase_box();
ix = Fl::event_x(); if (ix<x()) ix=x(); if (ix>=x()+w()) ix=x()+w()-1;
iy = Fl::event_y(); if (iy<y()) iy=y(); if (iy>=y()+h()) iy=y()+h()-1;
dragged = 0;
button = Fl::event_button();
return 1;
case FL_DRAG:
dragged = 1;
erase_box();
x2 = Fl::event_x(); if (x2<x()) x2=x(); if (x2>=x()+w()) x2=x()+w()-1;
y2 = Fl::event_y(); if (y2<y()) y2=y(); if (y2>=y()+h()) y2=y()+h()-1;
if (button != 1) {ix = x2; iy = y2; return 1;}
if (ix < x2) {sx = ix; sw = x2-ix;} else {sx = x2; sw = ix-x2;}
if (iy < y2) {sy = iy; sh = y2-iy;} else {sy = y2; sh = iy-y2;}
window()->make_current();
fl_overlay_rect(sx,sy,sw,sh);
return 1;
case FL_RELEASE:
if (button == 1) {
erase_box();
if (dragged && sw > 3 && sh > 3) {
X = X + (sx+sw/2-x()-W/2)*scale/W;
Y = Y + (-sy-sh/2+y()+H/2)*scale/W;
scale = sw*scale/W;
} else if (!dragged) {
scale = 2*scale;
if (julia) {
if (scale >= 4) {
scale = 4;
X = Y = 0;
}
} else {
if (scale >= 2.5) {
scale = 2.5;
X = -.75;
Y = 0;
}
}
} else return 1;
((Drawing_Window*)(user_data()))->update_label();
new_display();
} else if (!julia) {
if (!jbrot.d) {
make_window(jbrot);
jbrot.d->julia = 1;
jbrot.d->X = 0;
jbrot.d->Y = 0;
jbrot.d->scale = 4;
jbrot.update_label();
}
jbrot.d->jX = X + (ix-x()-W/2)*scale/W;
jbrot.d->jY = Y + (H/2-iy+y())*scale/W;
static char buffer[128];
sprintf(buffer, "Julia %.7f %.7f",jbrot.d->jX,jbrot.d->jY);
jbrot.window->label(buffer);
jbrot.window->show();
jbrot.d->new_display();
}
return 1;
}
return 0;
}
void Drawing_Area::new_display() {
drawn = nextline = 0;
set_idle();
}
void Drawing_Area::resize(int X,int Y,int W,int H) {
if (W != w() || H != h()) {
this->W = W-6;
this->H = H-8;
if (buffer) {delete[] buffer; buffer = 0; new_display();}
}
Fl_Box::resize(X,Y,W,H);
}
void brightness_slider_cb(Fl_Slider* o, Drawing_Window* s) {
s->d->brightness = int(o->value());
s->d->new_display();
}
void iterations_slider_cb(Fl_Slider* o, Drawing_Window* s) {
s->d->iterations = 1<<int(o->value());
s->d->new_display();
}
void x_callback(Fl_Input* o, Drawing_Window* s) {
double v = atof(o->value());
s->d->X = v;
s->d->new_display();
}
void y_callback(Fl_Input* o, Drawing_Window* s) {
double v = atof(o->value());
s->d->Y = v;
s->d->new_display();
}
void w_callback(Fl_Input* o, Drawing_Window* s) {
double v = atof(o->value());
s->d->scale = v;
s->d->new_display();
}