https://github.com/dannycalegari/schottky
Tip revision: 79f4e854356c043ac627bad942d2b339dd34e121 authored by Alden Walker on 07 November 2014, 20:40:38 UTC
doc
doc
Tip revision: 79f4e85
ifs_gui.cc
#include <map>
#include <set>
#include <cstdlib>
#include "ifs_gui.h"
#include "movie.h"
/***************************************************************************
* widget functions
***************************************************************************/
bool Widget::contains_pixel(int x, int y) {
return (ul.x <= x) && (x < ul.x + width) && (ul.y <= y) && (y < ul.y + height);
}
bool Widget::intersects_rectangle(const Point2d<int>& p, int w, int h) {
return !(ul.x > p.x + w || ul.y > p.y + h || p.x > ul.x + width || p.y > ul.y + height);
}
void Widget::clear() {
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, ifsg->main_window, gc, ul.x, ul.y, width, height);
}
WidgetDraw::WidgetDraw(IFSGui* i, int w, int h, void (IFSGui::*f)(XEvent*)) {
width = w;
height = h;
ifsg = i;
click_signal = f;
p = XCreatePixmap(ifsg->display, ifsg->main_window,
width, height, DefaultDepth(ifsg->display, ifsg->screen));
gc = XCreateGC(ifsg->display, RootWindow(ifsg->display, ifsg->screen), 0, NULL);
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XDrawRectangle(ifsg->display, p, gc, 0, 0, width-1, height-1);
}
void WidgetDraw::redraw() {
initial_draw();
}
void WidgetDraw::initial_draw() {
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
}
WidgetButton::WidgetButton(IFSGui* i, const std::string& t, int w, int h, void (IFSGui::*f)(XEvent*)) {
ifsg = i;
width = w;
height = h;
text = t;
click_signal = f;
gc = XCreateGC(ifsg->display, RootWindow(ifsg->display, ifsg->screen), 0, NULL);
XFontStruct* font = XLoadQueryFont(ifsg->display, "fixed");
XSetFont(ifsg->display, gc, font->fid);
XCharStruct te;
int fdir, fdescent, fascent;
XTextExtents(font, text.c_str(), text.size(), &fdir, &fascent, &fdescent, &te);
int desired_width = te.rbearing - te.lbearing;
int width_offset = desired_width/2;
int height_offset = (te.ascent - te.descent)/2;
if (w > 0) {
width = w;
} else {
width = desired_width + 10;
}
text_position = Point2d<int>(width/2 - width_offset, height/2 + height_offset);
p = XCreatePixmap(ifsg->display, ifsg->main_window,
width, height, DefaultDepth(ifsg->display, ifsg->screen));
//clear the pixmap
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
//set the real colors
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
//draw the square
XSetLineAttributes(ifsg->display, gc, 0, LineSolid, CapButt, JoinMiter);
XDrawLine(ifsg->display, p, gc, 1, 1, 1, height-2);
XDrawLine(ifsg->display, p, gc, 1, height-2, width-2, height-2);
XDrawLine(ifsg->display, p, gc, width-2, height-2, width-2, 1);
XDrawLine(ifsg->display, p, gc, width-2, 1, 1, 1);
//draw the label
XDrawString(ifsg->display, p, gc, text_position.x, text_position.y, text.c_str(), text.size());
}
void WidgetButton::initial_draw() {
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
}
void WidgetButton::redraw() {
initial_draw();
}
WidgetText::WidgetText(IFSGui* i, const std::string& t, int w, int h) {
ifsg = i;
text = t;
height = h;
click_signal = NULL;
gc = XCreateGC(ifsg->display, RootWindow(ifsg->display, ifsg->screen), 0, NULL);
XFontStruct* font = XLoadQueryFont(ifsg->display, "fixed");
XSetFont(ifsg->display, gc, font->fid);
XCharStruct te;
int fdir, fdescent, fascent;
XTextExtents(font, text.c_str(), text.size(), &fdir, &fascent, &fdescent, &te);
int desired_width = te.rbearing - te.lbearing;
//int width_offset = desired_width/2;
int height_offset = (te.ascent - te.descent)/2;
if (w > 0) {
width = w;
} else {
width = desired_width + 10;
}
text_position = Point2d<int>(5, height/2 + height_offset);
//text_position = Point2d<int>(5, height/2);
p = XCreatePixmap(ifsg->display, ifsg->main_window,
width, height, DefaultDepth(ifsg->display, ifsg->screen));
//clear the pixmap
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
//set the real colors
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
//draw the label
XDrawString(ifsg->display, p, gc, text_position.x, text_position.y, text.c_str(), text.size());
}
void WidgetText::update_text(const std::string& s) {
text = s;
//clear it
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XDrawString(ifsg->display, p, gc, text_position.x, text_position.y, text.c_str(), text.size());
redraw();
}
void WidgetText::redraw() {
initial_draw();
}
void WidgetText::initial_draw() {
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
//std::cout << "Drawing string: " << text << "\n";
//std::cout << "At position: " << ul.x << " " << ul.y << "\n";
}
WidgetCheck::WidgetCheck(IFSGui* i, const std::string& t, int w, int h, bool c, void (IFSGui::*f)(XEvent*)) {
width = w;
height = h;
ifsg = i;
text = t;
checked = c;
click_signal = f;
gc = XCreateGC(ifsg->display, RootWindow(ifsg->display, ifsg->screen), 0, NULL);
XFontStruct* font = XLoadQueryFont(ifsg->display, "fixed");
XSetFont(ifsg->display, gc, font->fid);
XCharStruct te;
int fdir, fdescent, fascent;
XTextExtents(font, text.c_str(), text.size(), &fdir, &fascent, &fdescent, &te);
int desired_width = te.rbearing - te.lbearing;
//int width_offset = desired_width/2;
int height_offset = (te.ascent - te.descent)/2;
if (w > 0) {
width = w;
} else {
width = desired_width + 10 + 10 + 5;
}
text_position = Point2d<int>(20, height/2 + height_offset+1);
p = XCreatePixmap(ifsg->display, ifsg->main_window,
width, height, DefaultDepth(ifsg->display, ifsg->screen));
//clear the pixmap
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
//set the real colors
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
//draw the check box
if (checked) {
XFillRectangle(ifsg->display, p, gc, 5, height/2-5, 11, 11);
} else {
XDrawRectangle(ifsg->display, p, gc, 5, height/2-5, 10, 10);
}
//draw the label
XDrawString(ifsg->display, p, gc, text_position.x, text_position.y, text.c_str(), text.size());
}
void WidgetCheck::redraw() {
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
if (checked) {
XFillRectangle(ifsg->display, p, gc, 5, height/2-5, 11, 11);
} else {
XDrawRectangle(ifsg->display, p, gc, 5, height/2-5, 10, 10);
}
XDrawString(ifsg->display, p, gc, text_position.x, text_position.y, text.c_str(), text.size());
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
}
void WidgetCheck::initial_draw() {
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
}
WidgetLeftArrow::WidgetLeftArrow(IFSGui* i, int w, int h, void (IFSGui::*f)(XEvent*)) {
ifsg = i;
width = w;
height = h;
click_signal = f;
p = XCreatePixmap(ifsg->display, ifsg->main_window,
width, height, DefaultDepth(ifsg->display, ifsg->screen));
gc = XCreateGC(ifsg->display, RootWindow(ifsg->display, ifsg->screen), 0, NULL);
//clear the pixmap
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
//set the real colors
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
//draw the left arrow box
XPoint tri[3];
tri[0].x = width-5; tri[0].y = 5;
tri[1].x = 5; tri[1].y = height/2;
tri[2].x = width-5; tri[2].y = height-5;
XFillPolygon(ifsg->display, p, gc, tri, 3, Convex, CoordModeOrigin);
}
void WidgetLeftArrow::initial_draw() {
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
}
void WidgetLeftArrow::redraw() {
initial_draw();
}
WidgetRightArrow::WidgetRightArrow(IFSGui* i, int w, int h, void (IFSGui::*f)(XEvent*)) {
ifsg = i;
width = w;
height = h;
click_signal = f;
p = XCreatePixmap(ifsg->display, ifsg->main_window,
width, height, DefaultDepth(ifsg->display, ifsg->screen));
gc = XCreateGC(ifsg->display, RootWindow(ifsg->display, ifsg->screen), 0, NULL);
//clear the pixmap
XSetForeground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
XFillRectangle(ifsg->display, p, gc, 0, 0, width, height);
//set the real colors
XSetForeground(ifsg->display, gc, BlackPixel(ifsg->display, ifsg->screen));
XSetBackground(ifsg->display, gc, WhitePixel(ifsg->display, ifsg->screen));
//draw the right arrow box
XPoint tri[3];
tri[0].x = 5; tri[0].y = 5;
tri[1].x = 5; tri[1].y = height-5;
tri[2].x = width-5; tri[2].y = height/2;
XFillPolygon(ifsg->display, p, gc, tri, 3, Convex, CoordModeOrigin);
}
void WidgetRightArrow::initial_draw() {
XCopyArea(ifsg->display, p, ifsg->main_window, gc, 0, 0, width, height, ul.x, ul.y);
}
void WidgetRightArrow::redraw() {
initial_draw();
}
/****************************************************************************
* signal handlers
****************************************************************************/
void IFSGui::S_switch_to_limit(XEvent* e) {
if (e->type != ButtonPress) return;
window_mode = LIMIT;
reset_and_pack_window();
}
void IFSGui::S_switch_to_mandelbrot(XEvent* e) {
if (e->type != ButtonPress) return;
window_mode = MANDELBROT;
reset_and_pack_window();
}
void IFSGui::S_switch_to_combined(XEvent* e) {
if (e->type != ButtonPress) return;
window_mode = BOTH;
reset_and_pack_window();
}
//limit set
void IFSGui::S_limit_draw(XEvent* e) {
if (e->type == KeyPress || e->type == MotionNotify) return;
//if we clicked, center the window
//on the mouse pointer
if (e->type == ButtonPress) {
int widget_x = e->xbutton.x - W_limit_plot.ul.x;
int widget_y = e->xbutton.y - W_limit_plot.ul.y;
cpx c = limit_pixel_to_cpx(Point2d<int>(widget_x, widget_y));
recenter_limit(c);
}
}
void IFSGui::S_limit_increase_depth(XEvent* e) {
if (e->type == MotionNotify) return;
++limit_depth;
std::stringstream T; T.str(""); T << limit_depth;
W_limit_depth_label.update_text(T.str());
draw_limit();
}
void IFSGui::S_limit_decrease_depth(XEvent* e) {
if (e->type == KeyPress || e->type == MotionNotify) return;
--limit_depth;
std::stringstream T; T.str(""); T << limit_depth;
W_limit_depth_label.update_text(T.str());
draw_limit();
}
void IFSGui::S_limit_auto_depth(XEvent* e) {
if (e->type != ButtonPress) return;
limit_auto_depth = !limit_auto_depth;
W_limit_depth_auto.checked = limit_auto_depth;
W_limit_depth_auto.redraw();
draw_limit();
}
void IFSGui::S_limit_switch_chunky(XEvent* e) {
if (e->type == KeyPress || e->type == MotionNotify) return;
limit_chunky = !limit_chunky;
W_limit_chunky.checked = limit_chunky;
W_limit_chunky.redraw();
draw_limit();
}
void IFSGui::S_limit_switch_colors(XEvent* e) {
if (e->type == KeyPress || e->type == MotionNotify) return;
limit_colors = !limit_colors;
W_limit_colors.checked = limit_colors;
W_limit_colors.redraw();
draw_limit();
}
void IFSGui::S_limit_zoom_in(XEvent* e) {
if (e->type == ButtonPress) {
double radius = (limit_ur.real() - limit_ll.real())/2.0;
radius /= 1.5;
cpx center = (limit_ll + limit_ur) / 2.0;
limit_ll = center - cpx(radius, radius);
limit_ur = center + cpx(radius, radius);
limit_pixel_width = (limit_ur.real() - limit_ll.real())/double(W_limit_plot.width);
draw_limit();
}
}
void IFSGui::S_limit_zoom_out(XEvent* e) {
if (e->type == ButtonPress) {
double radius = (limit_ur.real() - limit_ll.real())/2.0;
radius *= 1.5;
cpx center = (limit_ll + limit_ur) / 2.0;
limit_ll = center - cpx(radius, radius);
limit_ur = center + cpx(radius, radius);
limit_pixel_width = (limit_ur.real() - limit_ll.real())/double(W_limit_plot.width);
draw_limit();
}
}
void IFSGui::S_limit_uv_graph(XEvent* e) {
if (e->type != ButtonPress) return;
limit_uv_graph = !limit_uv_graph;
W_limit_uv_graph.checked = limit_uv_graph;
W_limit_uv_graph.redraw();
draw_limit();
}
void IFSGui::S_limit_uv_graph_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
if (limit_uv_graph_depth == 1) return;
--limit_uv_graph_depth;
std::stringstream T; T.str(""); T << limit_uv_graph_depth;
W_limit_uv_graph_depth_label.update_text(T.str());
draw_limit();
}
void IFSGui::S_limit_uv_graph_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++limit_uv_graph_depth;
std::stringstream T; T.str(""); T << limit_uv_graph_depth;
W_limit_uv_graph_depth_label.update_text(T.str());
draw_limit();
}
void IFSGui::S_limit_nifs(XEvent* e) {
if (e->type != ButtonPress) return;
limit_nifs = !limit_nifs;
W_limit_nifs.checked = limit_nifs;
W_limit_nifs.redraw();
if (limit_2d || limit_gifs) {
limit_2d = W_limit_2d.checked = false;
//limit_gifs = W_limit_gifs.checked = false;
W_limit_2d.redraw();
//W_limit_gifs.redraw();
}
draw_limit();
mand_grid_connected_valid = false;
if (mand_connected) draw_mand();
}
void IFSGui::S_limit_gifs(XEvent* e) {
if (e->type != ButtonPress) return;
limit_gifs = !limit_gifs;
W_limit_gifs.checked = limit_gifs;
W_limit_gifs.redraw();
if (limit_2d || limit_nifs) {
limit_2d = W_limit_2d.checked = false;
limit_nifs = W_limit_nifs.checked = false;
W_limit_2d.redraw();
W_limit_nifs.redraw();
}
draw_limit();
mand_grid_connected_valid = false;
if (mand_connected) draw_mand();
}
void IFSGui::S_limit_2d(XEvent* e) {
if (e->type != ButtonPress) return;
limit_2d = !limit_2d;
W_limit_2d.checked = limit_2d;
W_limit_2d.redraw();
if (limit_nifs || limit_gifs) {
limit_nifs = W_limit_nifs.checked = false;
//limit_gifs = W_limit_gifs.checked = false;
W_limit_nifs.redraw();
//W_limit_gifs.redraw();
mand_grid_connected_valid = false;
if (mand_connected) draw_mand();
}
draw_limit();
}
//mandelbrot
void IFSGui::S_mand_draw(XEvent* e) {
if (e->type == KeyPress) return;
//if we're drawing a loop, and we click, we need to add that to
//the loop
if (e->type == ButtonPress && currently_drawing_path) {
int widget_x = e->xbutton.x - W_mand_plot.ul.x;
int widget_y = e->xbutton.y - W_mand_plot.ul.y;
cpx c = mand_pixel_to_cpx(Point2d<int>(widget_x, widget_y));
path.path.push_back(c);
//draw the next line
int rcol = get_rgb_color(1,0.2,1);
Widget& MW = W_mand_plot;
XSetForeground(display, MW.gc, rcol);
if (path.path.size() == 1) {
XDrawPoint(display, MW.p, MW.gc, widget_x, widget_y);
XCopyArea(display, MW.p, main_window, MW.gc, widget_x, widget_y,
1,1,
MW.ul.x + widget_x, MW.ul.y + widget_y);
} else {
Point2d<int> p = mand_cpx_to_pixel(path.path[path.path.size()-2]);
XDrawLine(display, MW.p, MW.gc, p.x, p.y, widget_x, widget_y);
XCopyArea(display, MW.p, main_window, MW.gc, 0,0,
MW.width, MW.height,
MW.ul.x, MW.ul.y);
}
//the following is run if the button is pressed or if there is
//motion where the button is down
} else if ( (e->type == ButtonPress && e->xbutton.button == Button1) ||
(e->type == MotionNotify && ((e->xmotion.state >> 8)&1)) ) {
int widget_x = e->xbutton.x - W_mand_plot.ul.x;
int widget_y = e->xbutton.y - W_mand_plot.ul.y;
cpx c = mand_pixel_to_cpx(Point2d<int>(widget_x, widget_y));
//std::cout << "Moving IFS to " << widget_x << " " << widget_y << "=" << c << "\n";
change_highlighted_ifs(c);
//it's a right mouse click -- zoom in
} else if (e->type == ButtonPress && e->xbutton.button == Button3) {
int widget_x = e->xbutton.x - W_mand_plot.ul.x;
int widget_y = e->xbutton.y - W_mand_plot.ul.y;
cpx c = mand_pixel_to_cpx(Point2d<int>(widget_x, widget_y));
IFS.set_params(c,c);
mand_zoom(0.5);
recompute_point_data();
}
//additionally, if the mouse is moved, we need to update the
//text
if (e->type == MotionNotify) {
int widget_x = e->xbutton.x - W_mand_plot.ul.x;
int widget_y = e->xbutton.y - W_mand_plot.ul.y;
cpx c = mand_pixel_to_cpx(Point2d<int>(widget_x, widget_y));
std::stringstream T; T.str("");
T.precision(15);
T << "Re: " << std::real(c);
W_mand_mouse_X.update_text(T.str());
T.str("");
T << "Im: " << std::imag(c);
W_mand_mouse_Y.update_text(T.str());
}
}
void IFSGui::S_mand_recenter(XEvent* e) {
if (e->type == ButtonPress) mand_recenter();
}
void IFSGui::S_mand_zoom_in(XEvent* e) {
if (e->type == ButtonPress) mand_zoom(0.5);
}
void IFSGui::S_mand_zoom_out(XEvent* e) {
if (e->type == ButtonPress) mand_zoom(2.0);
}
void IFSGui::S_mand_decrease_mesh(XEvent* e) {
if (e->type == ButtonPress) {
if (mand_pixel_group_size == 1) return;
mand_pixel_group_size /= 2;
std::stringstream T; T.str(""); T << mand_pixel_group_size;
W_mand_mesh_label.update_text(T.str());
mand_reset_mesh();
draw_mand();
}
}
void IFSGui::S_mand_increase_mesh(XEvent* e) {
if (e->type == ButtonPress) {
mand_pixel_group_size *= 2;
std::stringstream T; T.str(""); T << mand_pixel_group_size;
W_mand_mesh_label.update_text(T.str());
mand_reset_mesh();
draw_mand();
}
}
void IFSGui::S_mand_connected(XEvent* e) {
if (e->type == ButtonPress) {
mand_connected = !mand_connected;
W_mand_connected_check.checked = mand_connected;
W_mand_connected_check.redraw();
draw_mand();
}
}
void IFSGui::S_mand_connected_increase_depth(XEvent* e) {
if (e->type == ButtonPress) {
++mand_connected_depth;
std::stringstream T; T.str(""); T << mand_connected_depth;
W_mand_connected_depth_label.update_text(T.str());
mand_grid_connected_valid = false;
if (mand_connected) draw_mand();
}
}
void IFSGui::S_mand_connected_decrease_depth(XEvent* e) {
if (e->type == ButtonPress) {
--mand_connected_depth;
std::stringstream T; T.str(""); T << mand_connected_depth;
W_mand_connected_depth_label.update_text(T.str());
mand_grid_connected_valid = false;
if (mand_connected) draw_mand();
}
}
void IFSGui::S_mand_contains_half(XEvent* e) {
if (e->type == ButtonPress) {
mand_contains_half = !mand_contains_half;
W_mand_contains_half_check.checked = mand_contains_half;
W_mand_contains_half_check.redraw();
draw_mand();
}
}
void IFSGui::S_mand_contains_half_increase_depth(XEvent* e) {
if (e->type == ButtonPress) {
++mand_contains_half_depth;
std::stringstream T; T.str(""); T << mand_contains_half_depth;
W_mand_contains_half_depth_label.update_text(T.str());
mand_grid_contains_half_valid = false;
if (mand_contains_half) draw_mand();
}
}
void IFSGui::S_mand_contains_half_decrease_depth(XEvent* e) {
if (e->type == ButtonPress) {
--mand_contains_half_depth;
std::stringstream T; T.str(""); T << mand_contains_half_depth;
W_mand_contains_half_depth_label.update_text(T.str());
mand_grid_contains_half_valid = false;
if (mand_contains_half) draw_mand();
}
}
void IFSGui::S_mand_trap(XEvent* e) {
if (e->type == ButtonPress) {
mand_trap = !mand_trap;
W_mand_trap_check.checked = mand_trap;
W_mand_trap_check.redraw();
draw_mand();
}
}
void IFSGui::S_mand_trap_increase_depth(XEvent* e) {
if (e->type == ButtonPress) {
++mand_trap_depth;
std::stringstream T; T.str(""); T << mand_trap_depth;
W_mand_trap_depth_label.update_text(T.str());
mand_grid_trap_valid = false;
if (mand_trap) draw_mand();
}
}
void IFSGui::S_mand_trap_decrease_depth(XEvent* e) {
if (e->type == ButtonPress) {
--mand_trap_depth;
std::stringstream T; T.str(""); T << mand_trap_depth;
W_mand_trap_depth_label.update_text(T.str());
mand_grid_trap_valid = false;
if (mand_trap) draw_mand();
}
}
void IFSGui::S_mand_limit_trap(XEvent* e) {
if (e->type == ButtonPress) {
mand_limit_trap = !mand_limit_trap;
W_mand_limit_trap_check.checked = mand_limit_trap;
W_mand_limit_trap_check.redraw();
mand_grid_trap_valid = false;
if (mand_trap) draw_mand();
}
}
void IFSGui::S_mand_dirichlet(XEvent* e) {
if (e->type != ButtonPress) return;
mand_dirichlet = !mand_dirichlet;
W_mand_dirichlet_check.checked = mand_dirichlet;
W_mand_dirichlet_check.redraw();
draw_mand();
}
void IFSGui::S_mand_dirichlet_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--mand_dirichlet_depth;
std::stringstream T;
T.str(""); T << mand_dirichlet_depth;
W_mand_dirichlet_depth_label.update_text(T.str());
mand_grid_dirichlet_valid = false;
if (mand_dirichlet) draw_mand();
}
void IFSGui::S_mand_dirichlet_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++mand_dirichlet_depth;
std::stringstream T;
T.str(""); T << mand_dirichlet_depth;
W_mand_dirichlet_depth_label.update_text(T.str());
mand_grid_dirichlet_valid = false;
if (mand_dirichlet) draw_mand();
}
void IFSGui::S_mand_set_C(XEvent* e) {
if (e->type != ButtonPress) return;
mand_set_C = !mand_set_C;
W_mand_set_C_check.checked = mand_set_C;
W_mand_set_C_check.redraw();
draw_mand();
}
void IFSGui::S_mand_set_C_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--mand_set_C_depth;
std::stringstream T;
T.str(""); T << mand_set_C_depth;
W_mand_set_C_depth_label.update_text(T.str());
mand_grid_set_C_valid = false;
if (mand_set_C) draw_mand();
}
void IFSGui::S_mand_set_C_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++mand_set_C_depth;
std::stringstream T;
T.str(""); T << mand_set_C_depth;
W_mand_set_C_depth_label.update_text(T.str());
mand_grid_set_C_valid = false;
if (mand_set_C) draw_mand();
}
void IFSGui::S_mand_theta(XEvent* e) {
if (e->type != ButtonPress) return;
mand_theta = !mand_theta;
W_mand_theta_check.checked = mand_theta;
W_mand_theta_check.redraw();
draw_mand();
}
void IFSGui::S_mand_theta_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--mand_theta_depth;
std::stringstream T;
T.str(""); T << mand_theta_depth;
W_mand_theta_depth_label.update_text(T.str());
mand_grid_theta_valid = false;
if (mand_theta) draw_mand();
}
void IFSGui::S_mand_theta_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++mand_theta_depth;
std::stringstream T;
T.str(""); T << mand_theta_depth;
W_mand_theta_depth_label.update_text(T.str());
mand_grid_theta_valid = false;
if (mand_theta) draw_mand();
}
void IFSGui::S_mand_output_window(XEvent* e) {
if (e->type != ButtonPress) return;
int old_prec = std::cout.precision();
std::cout.precision(15);
std::cout << "Lower left: " << mand_ll << ", upper right: " << mand_ur << "\n";
std::cout.precision(old_prec);
}
void IFSGui::S_mand_output_picture(XEvent* e) {
if (e->type != ButtonPress) return;
std::vector<std::vector<Point3d<unsigned char> > > bmp(mand_output_picture_size);
for (int i=0; i<mand_output_picture_size; ++i) {
bmp[i].resize(mand_output_picture_size);
}
IFS.draw_mand_to_array(bmp, mand_ll, mand_ur,
(mand_connected ? mand_connected_depth : 0),
(mand_contains_half ? mand_contains_half_depth : 0));
//double PI = 3.14159265358979;
//IFS.draw_mand_to_array_radial(bmp,
// mand_output_picture_size,
// 0.89*1/sqrt(2.0), 1.01*(1/sqrt(2.0)),
// PI/2.0, 0.04,
// (mand_connected ? mand_connected_depth : 0),
// (mand_contains_half ? mand_contains_half_depth : 0));
write_bitmap(bmp, "mandelbrot_output.bmp");
std::cout << "Wrote bitmap\n";
}
void IFSGui::S_mand_output_picture_increase_size(XEvent* e) {
if (e->type != ButtonPress) return;
mand_output_picture_size += 50;
std::stringstream T;
T.str(""); T << mand_output_picture_size;
W_mand_output_picture_size_label.update_text(T.str());
}
void IFSGui::S_mand_output_picture_decrease_size(XEvent* e) {
if (e->type != ButtonPress) return;
if (mand_output_picture_size >= 50) mand_output_picture_size -= 50;
std::stringstream T;
T.str(""); T << mand_output_picture_size;
W_mand_output_picture_size_label.update_text(T.str());
}
//point
void IFSGui::S_point_connected(XEvent* e) {
if (e->type != ButtonPress) return;
point_connected_check = !point_connected_check;
W_point_connected_check.checked = point_connected_check;
W_point_connected_check.redraw();
recompute_point_data();
}
void IFSGui::S_point_connected_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++point_connected_depth;
std::stringstream T; T.str(""); T << point_connected_depth;
W_point_connected_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_connected_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--point_connected_depth;
std::stringstream T; T.str(""); T << point_connected_depth;
W_point_connected_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_contains_half(XEvent* e) {
if (e->type != ButtonPress) return;
point_contains_half_check = !point_contains_half_check;
W_point_contains_half_check.checked = point_contains_half_check;
W_point_contains_half_check.redraw();
recompute_point_data();
}
void IFSGui::S_point_contains_half_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++point_contains_half_depth;
std::stringstream T; T.str(""); T << point_contains_half_depth;
W_point_contains_half_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_contains_half_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--point_contains_half_depth;
std::stringstream T; T.str(""); T << point_contains_half_depth;
W_point_contains_half_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_uv_words(XEvent* e) {
if (e->type != ButtonPress) return;
point_uv_words_check = !point_uv_words_check;
W_point_uv_words_check.checked = point_uv_words_check;
W_point_uv_words_check.redraw();
recompute_point_data();
}
void IFSGui::S_point_uv_words_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++point_uv_words_depth;
std::stringstream T; T.str(""); T << point_uv_words_depth;
W_point_uv_words_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_uv_words_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--point_uv_words_depth;
std::stringstream T; T.str(""); T << point_uv_words_depth;
W_point_uv_words_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_trap(XEvent* e) {
if (e->type != ButtonPress) return;
point_trap_check = !point_trap_check;
W_point_trap_check.checked = point_trap_check;
W_point_trap_check.redraw();
recompute_point_data();
}
void IFSGui::S_point_trap_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++point_trap_depth;
std::stringstream T; T.str(""); T << point_trap_depth;
W_point_trap_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_trap_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--point_trap_depth;
std::stringstream T; T.str(""); T << point_trap_depth;
W_point_trap_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_coordinates(XEvent* e) {
if (e->type != ButtonPress) return;
point_coordinates_check = !point_coordinates_check;
W_point_coordinates_check.checked = point_coordinates_check;
W_point_coordinates_check.redraw();
recompute_point_data();
}
void IFSGui::S_point_coordinates_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++point_coordinates_depth;
std::stringstream T; T.str(""); T << point_coordinates_depth;
W_point_coordinates_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_point_coordinates_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--point_coordinates_depth;
std::stringstream T; T.str(""); T << point_coordinates_depth;
W_point_coordinates_depth_label.update_text(T.str());
recompute_point_data();
}
void IFSGui::S_mand_path_create_by_drawing_button(XEvent* e) {
if (e->type != ButtonPress) return;
currently_drawing_path = true;
path = IFSPath();
path.is_valid = true;
make_path_drawing_buttons();
}
void IFSGui::S_mand_path_create_by_boundary(XEvent* e) {
if (e->type != ButtonPress) return;
//make a grid of what's connected
std::vector<std::vector<bool> > grid(mand_num_pixel_groups,
std::vector<bool>(mand_num_pixel_groups, false));
for (int i=0; i<mand_num_pixel_groups; ++i) {
for (int j=0; j<mand_num_pixel_groups; ++j) {
grid[i][j] = (mand_data_grid[i][mand_num_pixel_groups-j-1].x > 0);
}
}
Point2d<int> p = mand_cpx_to_pixel_group(IFS.z);
p.y = mand_num_pixel_groups - p.y -1;
path = IFSPath();
IFS.hole_boundary_containing_point_from_grid(path.path, path.closed, grid, p, mand_ll, mand_ur, 0);
path.is_valid = true;
make_path_task_buttons(false);
draw_mand();
}
void IFSGui::S_mand_path_finish_cancel(XEvent* e) {
if (e->type != ButtonPress) return;
currently_drawing_path = false;
path = IFSPath();
make_path_creation_buttons(true);
draw_mand();
}
void IFSGui::S_mand_path_finish_path(XEvent* e) {
if (e->type != ButtonPress) return;
currently_drawing_path = false;
path.closed = false;
make_path_task_buttons(true);
}
void IFSGui::S_mand_path_finish_loop(XEvent* e) {
if (e->type != ButtonPress) return;
currently_drawing_path = false;
path.closed = true;
make_path_task_buttons(true);
Point2d<int> p1 = mand_cpx_to_pixel(path.path[path.path.size()-1]);
Point2d<int> p2 = mand_cpx_to_pixel(path.path[0]);
Widget& MW = W_mand_plot;
XSetForeground(display, MW.gc, get_rgb_color(1,0.2,1));
XDrawLine(display, MW.p, MW.gc, p1.x, p1.y, p2.x, p2.y);
XCopyArea(display, MW.p, main_window, MW.gc, 0,0,
MW.width, MW.height,
MW.ul.x, MW.ul.y);
}
void IFSGui::S_mand_path_delete(XEvent* e) {
if (e->type != ButtonPress) return;
path = IFSPath();
make_path_creation_buttons(false);
draw_mand();
}
void IFSGui::S_mand_path_find_traps(XEvent* e) {
if (e->type != ButtonPress) return;
find_traps_along_path(0);
}
void IFSGui::S_mand_path_find_coordinates(XEvent* e) {
if (e->type != ButtonPress) return;
find_coordinates_along_path(0);
}
void IFSGui::S_mand_path_create_movie(XEvent* e) {
if (e->type != ButtonPress || !path.is_valid) return;
//create the mandelbrot connectedness grid
std::vector<std::vector<bool> > mand_connected_grid;
if (path.movie_with_mandelbrot) {
mand_connected_grid = std::vector<std::vector<bool> >(mand_data_grid.size(), std::vector<bool>(mand_data_grid.size(), false));
for (int i=0; i<(int)mand_data_grid.size(); ++i) {
for (int j=0; j<(int)mand_data_grid.size(); ++j) {
mand_connected_grid[i][mand_data_grid.size()-j-1] = (mand_data_grid[i][j].x >= 0);
}
}
}
(void)ifs_movie_from_path(IFS, path.path, path.closed, "ifs_movie",
limit_ll, limit_ur, limit_depth,
path.movie_with_mandelbrot, &mand_ll, &mand_ur, &mand_connected_grid,
W_limit_plot.width, W_limit_plot.height,
path.movie_fps, path.movie_length, 1);
}
void IFSGui::S_mand_path_movie_decrease_length(XEvent* e) {
if (e->type != ButtonPress) return;
if (path.movie_length >= 1) {
--path.movie_length;
std::stringstream T; T.str(""); T << path.movie_length;
W_mand_path_movie_length_label.update_text(T.str());
}
}
void IFSGui::S_mand_path_movie_increase_length(XEvent* e) {
if (e->type != ButtonPress) return;
++path.movie_length;
std::stringstream T; T.str(""); T << path.movie_length;
W_mand_path_movie_length_label.update_text(T.str());
}
void IFSGui::S_mand_path_movie_with_mandelbrot(XEvent* e) {
if (e->type != ButtonPress) return;
path.movie_with_mandelbrot = !path.movie_with_mandelbrot;
W_mand_path_movie_with_mandelbrot.checked = path.movie_with_mandelbrot;
W_mand_path_movie_with_mandelbrot.redraw();
}
void IFSGui::S_mand_path_find_uv_words(XEvent* e) {
if (e->type != ButtonPress || !path.is_valid) return;
ifs temp_IFS;
temp_IFS.find_closest_uv_words_along_path(path.path, path.closed, point_uv_words_depth);
}
void IFSGui::S_mand_path_find_half_words(XEvent* e) {
if (e->type != ButtonPress || !path.is_valid) return;
ifs temp_IFS;
path.half_words = temp_IFS.get_certified_half_balls_along_path(path.path, limit_depth, 1);
path.has_half_words = (path.half_words.size() > 0);
if (path.has_half_words) {
path.half_start = 0;
std::stringstream T; T.str(""); T << path.half_start;
W_mand_path_half_start_label.update_text(T.str());
path.half_end = path.half_words.size()-1;
T.str(""); T << path.half_end;
W_mand_path_half_end_label.update_text(T.str());
draw_mand();
}
}
void IFSGui::S_mand_path_half_increase_depth(XEvent* e) {
if (e->type != ButtonPress) return;
++path.half_depth;
std::stringstream T; T.str(""); T << path.half_depth;
W_mand_path_half_depth_label.update_text(T.str());
draw_mand();
}
void IFSGui::S_mand_path_half_decrease_depth(XEvent* e) {
if (e->type != ButtonPress) return;
--path.half_depth;
if (path.half_depth < 0) {
path.half_depth = 0;
return;
}
std::stringstream T; T.str(""); T << path.half_depth;
W_mand_path_half_depth_label.update_text(T.str());
draw_mand();
}
void IFSGui::S_mand_path_half_increase_start(XEvent* e) {
if (e->type != ButtonPress) return;
++path.half_start;
if (path.has_half_words && path.half_start >= (int)path.half_words.size()) {
path.half_start = 0;
}
std::stringstream T; T.str(""); T << path.half_start;
W_mand_path_half_start_label.update_text(T.str());
draw_mand();
}
void IFSGui::S_mand_path_half_decrease_start(XEvent* e) {
if (e->type != ButtonPress) return;
--path.half_start;
if (path.has_half_words && path.half_start < 0) {
path.half_start = path.half_words.size() - 1;
}
std::stringstream T; T.str(""); T << path.half_start;
W_mand_path_half_start_label.update_text(T.str());
draw_mand();
}
void IFSGui::S_mand_path_half_increase_end(XEvent* e) {
if (e->type != ButtonPress) return;
++path.half_end;
if (path.has_half_words && path.half_end >= (int)path.half_words.size()) {
path.half_end = 0;
}
std::stringstream T; T.str(""); T << path.half_end;
W_mand_path_half_end_label.update_text(T.str());
draw_mand();
}
void IFSGui::S_mand_path_half_decrease_end(XEvent* e) {
if (e->type != ButtonPress) return;
--path.half_end;
if (path.has_half_words && path.half_end < 0) {
path.half_end = path.half_words.size()-1;
}
std::stringstream T; T.str(""); T << path.half_end;
W_mand_path_half_end_label.update_text(T.str());
draw_mand();
}
void IFSGui::make_path_drawing_buttons() {
detach_widget(&W_mand_path_create_by_drawing_button);
detach_widget(&W_mand_path_create_by_boundary_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_drawing_title);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_finish_cancel_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_finish_path_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_finish_loop_button);
W_mand_path_drawing_title.initial_draw();
W_mand_path_finish_cancel_button.initial_draw();
W_mand_path_finish_path_button.initial_draw();
W_mand_path_finish_loop_button.initial_draw();
}
void IFSGui::make_path_task_buttons(bool created_by_drawing) {
//if it was created by drawing, we need to take those away
if (created_by_drawing) {
detach_widget(&W_mand_path_drawing_title);
detach_widget(&W_mand_path_finish_cancel_button);
detach_widget(&W_mand_path_finish_path_button);
detach_widget(&W_mand_path_finish_loop_button);
} else {
detach_widget(&W_mand_path_create_by_drawing_button);
detach_widget(&W_mand_path_create_by_boundary_button);
}
pack_widget_upper_right(&W_mand_plot, &W_mand_path_tasks_title);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_delete_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_traps_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_coordinates_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_create_movie_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_movie_length_title);
pack_widget_upper_right(&W_mand_path_movie_length_title, &W_mand_path_movie_decrease_length);
pack_widget_upper_right(&W_mand_path_movie_decrease_length, &W_mand_path_movie_length_label);
pack_widget_upper_right(&W_mand_path_movie_length_label, &W_mand_path_movie_increase_length);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_movie_with_mandelbrot);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_uv_words_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_half_words_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_half_depth_title);
pack_widget_upper_right(&W_mand_path_half_depth_title, &W_mand_path_half_depth_leftarrow);
pack_widget_upper_right(&W_mand_path_half_depth_leftarrow, &W_mand_path_half_depth_label);
pack_widget_upper_right(&W_mand_path_half_depth_label, &W_mand_path_half_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_half_start_stop_title);
pack_widget_upper_right(&W_mand_path_half_start_stop_title, &W_mand_path_half_start_leftarrow);
pack_widget_upper_right(&W_mand_path_half_start_leftarrow, &W_mand_path_half_start_label);
pack_widget_upper_right(&W_mand_path_half_start_label, &W_mand_path_half_start_rightarrow);
pack_widget_upper_right(&W_mand_path_half_start_rightarrow, &W_mand_path_half_end_leftarrow);
pack_widget_upper_right(&W_mand_path_half_end_leftarrow, &W_mand_path_half_end_label);
pack_widget_upper_right(&W_mand_path_half_end_label, &W_mand_path_half_end_rightarrow);
W_mand_path_tasks_title.initial_draw();
W_mand_path_delete_button.initial_draw();
W_mand_path_find_traps_button.initial_draw();
W_mand_path_find_coordinates_button.initial_draw();
W_mand_path_create_movie_button.initial_draw();
W_mand_path_movie_length_title.initial_draw();
W_mand_path_movie_decrease_length.initial_draw();
std::stringstream T; T.str(""); T << path.movie_length;
W_mand_path_movie_length_label.update_text(T.str());
W_mand_path_movie_with_mandelbrot.checked = path.movie_with_mandelbrot;
W_mand_path_movie_with_mandelbrot.initial_draw();
W_mand_path_movie_with_mandelbrot.redraw();
W_mand_path_movie_increase_length.initial_draw();
W_mand_path_find_uv_words_button.initial_draw();
W_mand_path_find_half_words_button.initial_draw();
W_mand_path_half_depth_title.initial_draw();
W_mand_path_half_depth_leftarrow.initial_draw();
T.str(""); T << path.half_depth;
W_mand_path_half_depth_label.update_text(T.str());
W_mand_path_half_depth_rightarrow.initial_draw();
W_mand_path_half_start_stop_title.initial_draw();
W_mand_path_half_start_leftarrow.initial_draw();
T.str(""); T << path.half_start;
W_mand_path_half_start_label.update_text(T.str());
W_mand_path_half_start_rightarrow.initial_draw();
W_mand_path_half_end_leftarrow.initial_draw();
T.str(""); T << path.half_end;
W_mand_path_half_end_label.update_text(T.str());
W_mand_path_half_end_rightarrow.initial_draw();
}
void IFSGui::make_path_creation_buttons(bool cancelling) {
if (cancelling) {
detach_widget(&W_mand_path_drawing_title);
detach_widget(&W_mand_path_finish_cancel_button);
detach_widget(&W_mand_path_finish_path_button);
detach_widget(&W_mand_path_finish_loop_button);
} else {
detach_widget(&W_mand_path_tasks_title);
detach_widget(&W_mand_path_delete_button);
detach_widget(&W_mand_path_find_traps_button);
detach_widget(&W_mand_path_find_coordinates_button);
detach_widget(&W_mand_path_create_movie_button);
detach_widget(&W_mand_path_movie_length_title);
detach_widget(&W_mand_path_movie_decrease_length);
detach_widget(&W_mand_path_movie_length_label);
detach_widget(&W_mand_path_movie_increase_length);
detach_widget(&W_mand_path_movie_with_mandelbrot);
detach_widget(&W_mand_path_find_uv_words_button);
detach_widget(&W_mand_path_find_half_words_button);
detach_widget(&W_mand_path_half_depth_title);
detach_widget(&W_mand_path_half_depth_leftarrow);
detach_widget(&W_mand_path_half_depth_label);
detach_widget(&W_mand_path_half_depth_rightarrow);
detach_widget(&W_mand_path_half_start_stop_title);
detach_widget(&W_mand_path_half_start_leftarrow);
detach_widget(&W_mand_path_half_start_label);
detach_widget(&W_mand_path_half_start_rightarrow);
detach_widget(&W_mand_path_half_end_leftarrow);
detach_widget(&W_mand_path_half_end_label);
detach_widget(&W_mand_path_half_end_rightarrow);
}
pack_widget_upper_right(&W_mand_plot, &W_mand_path_create_by_drawing_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_create_by_boundary_button);
W_mand_path_create_by_drawing_button.initial_draw();
W_mand_path_create_by_boundary_button.initial_draw();
}
/**************************************************************************
* back end functions
* ************************************************************************/
Point2d<int> IFSGui::limit_cpx_to_pixel(const cpx& c) {
int x = int( (c.real() - limit_ll.real()) / limit_pixel_width );
int real_y = int( (c.imag() - limit_ll.imag()) / limit_pixel_width );
int x11_y = W_limit_plot.height - real_y;
return Point2d<int>(x, x11_y);
}
cpx IFSGui::limit_pixel_to_cpx(const Point2d<int>& p) {
double r = (p.x+0.5)*limit_pixel_width + limit_ll.real();
double i = limit_ur.imag() - (p.y+0.5)*limit_pixel_width;
return cpx(r,i);
}
void IFSGui::draw_nifs_limit() {
//create the nifs object
//nIFS nifs(4, IFS.z);
nIFS nifs(3,IFS.z);
//nifs.centers[3] = -2; nifs.centers[4] = 2;
nifs.centers[0] = -1; nifs.centers[1] = 0; nifs.centers[2] = 1;
double min_r = nifs.minimal_initial_radius();
//std::cout << "Got min initial radius of " << min_r << "\n";
if (min_r < 0) return;
Widget& LW = W_limit_plot;
//clear the limit widget
XSetForeground(display, LW.gc, WhitePixel(display, screen));
XFillRectangle(display, LW.p, LW.gc, 0, 0, LW.width, LW.height);
XSetForeground(display, LW.gc, BlackPixel(display, screen));
XDrawRectangle(display, LW.p, LW.gc, 0, 0, LW.width-1, LW.height-1);
XSetFillStyle(display, LW.gc, FillSolid);
std::vector<int> colors(5);
colors[0] = get_rgb_color(1,0,0);
colors[1] = get_rgb_color(0,1,0);
colors[2] = get_rgb_color(0,0,1);
colors[3] = get_rgb_color(1,0,1);
colors[4] = get_rgb_color(0,1,1);
nBall initial_ball(0,min_r,1);
std::vector< nBall_stuff > stack(0);
stack.push_back( nBall_stuff(false, -1, 0, initial_ball) );
while (stack.size() > 0) {
nBall_stuff bs = stack.back();
stack.pop_back();
//if the ball is disjoint from the window, we might as well get rid of it
if (!bs.contained && bs.ball.is_disjoint(limit_ll, limit_ur)) continue;
if ( bs.depth >= limit_depth || bs.ball.radius < limit_pixel_width/2.0 ) {
Point2d<int> p = limit_cpx_to_pixel(bs.ball.center);
double r = bs.ball.radius / limit_pixel_width;
if (r <= 1.0) r = 1.0;
if (limit_colors) {
XSetForeground(display, LW.gc, colors[bs.last_gen]);
}
if (limit_chunky) {
XFillArc(display, LW.p, LW.gc, p.x-r, p.y-r, int(2.0*r), int(2.0*r), 23040, 23040);
} else {
XDrawPoint(display, LW.p, LW.gc, p.x, p.y);
}
continue;
}
//if the ball isn't disjoint from the window, maybe it is contained in it?
for (int i=0; i<3; ++i) {
nBall new_ball = nifs.act_on_right(i, bs.ball);
if (bs.contained) {
stack.push_back(nBall_stuff(true, (bs.last_gen==-1 ? i : bs.last_gen), bs.depth+1, new_ball));
} else {
if (bs.ball.is_contained(limit_ll, limit_ur)) {
stack.push_back(nBall_stuff(true, (bs.last_gen==-1 ? i : bs.last_gen), bs.depth+1, new_ball));
} else {
stack.push_back(nBall_stuff(false, (bs.last_gen==-1 ? i: bs.last_gen), bs.depth+1, new_ball));
}
}
}
}
//draw the marked points 0, 1/2, 1
for (int i=0; i<(int)limit_marked_points.size(); ++i) {
cpx& c = limit_marked_points[i];
int rcol = get_rgb_color(1,0.1,0);
if (limit_ll.real() < c.real() && c.real() < limit_ur.real() &&
limit_ll.imag() < c.imag() && c.imag() < limit_ur.imag()) {
Point2d<int> p = limit_cpx_to_pixel(c);
XSetForeground(display, LW.gc, rcol);
XFillArc(display, LW.p, LW.gc, p.x-3, p.y-3, 3, 3, 23040, 23040);
}
}
LW.redraw();
}
void IFSGui::draw_gifs_limit() {
double PI = 3.14159265358979323846;
//create the gifs object
std::vector<cpx> c(4);
std::vector<cpx> f(4);
c[0] = cpx(0,1.0);
c[1] = cpx(-sin(PI/3.0), -cos(PI/3.0));
c[2] = cpx(sin(PI/3.0), -cos(PI/3.0));
c[3] = cpx(0,0);
f[0] = IFS.z.real(); f[1] = IFS.z.real(); f[2] = IFS.z.real();
f[3] = IFS.z.imag();
gIFS gifs(f,c);
gBall initial_ball;
if (!gifs.minimal_ball(initial_ball)) return;
Widget& LW = W_limit_plot;
//clear the limit widget
XSetForeground(display, LW.gc, WhitePixel(display, screen));
XFillRectangle(display, LW.p, LW.gc, 0, 0, LW.width, LW.height);
XSetForeground(display, LW.gc, BlackPixel(display, screen));
XDrawRectangle(display, LW.p, LW.gc, 0, 0, LW.width-1, LW.height-1);
XSetFillStyle(display, LW.gc, FillSolid);
std::vector<int> colors(5);
colors[0] = get_rgb_color(1,0,0);
colors[1] = get_rgb_color(0,1,0);
colors[2] = get_rgb_color(0,0,1);
colors[3] = get_rgb_color(1,0,1);
std::vector< gBall_stuff > stack(0);
stack.push_back( gBall_stuff(false, -1, 0, initial_ball) );
while (stack.size() > 0) {
gBall_stuff bs = stack.back();
stack.pop_back();
//if the ball is disjoint from the window, we might as well get rid of it
if (!bs.contained && bs.ball.is_disjoint(limit_ll, limit_ur)) continue;
if ( bs.depth >= limit_depth || bs.ball.radius < limit_pixel_width/2.0 ) {
Point2d<int> p = limit_cpx_to_pixel(bs.ball.center);
double r = bs.ball.radius / limit_pixel_width;
if (r <= 1.0) r = 1.0;
if (limit_colors) {
XSetForeground(display, LW.gc, colors[bs.last_gen]);
}
if (limit_chunky) {
XFillArc(display, LW.p, LW.gc, p.x-r, p.y-r, int(2.0*r), int(2.0*r), 23040, 23040);
} else {
XDrawPoint(display, LW.p, LW.gc, p.x, p.y);
}
continue;
}
//if the ball isn't disjoint from the window, maybe it is contained in it?
for (int i=0; i<gifs.centers.size(); ++i) {
gBall new_ball = gifs.act_on_right(i, bs.ball);
if (bs.contained) {
stack.push_back(gBall_stuff(true, (bs.last_gen==-1 ? i : bs.last_gen), bs.depth+1, new_ball));
} else {
if (bs.ball.is_contained(limit_ll, limit_ur)) {
stack.push_back(gBall_stuff(true, (bs.last_gen==-1 ? i : bs.last_gen), bs.depth+1, new_ball));
} else {
stack.push_back(gBall_stuff(false, (bs.last_gen==-1 ? i: bs.last_gen), bs.depth+1, new_ball));
}
}
}
}
//draw the marked points 0, 1/2, 1
for (int i=0; i<(int)limit_marked_points.size(); ++i) {
cpx& c = limit_marked_points[i];
int rcol = get_rgb_color(1,0.1,0);
if (limit_ll.real() < c.real() && c.real() < limit_ur.real() &&
limit_ll.imag() < c.imag() && c.imag() < limit_ur.imag()) {
Point2d<int> p = limit_cpx_to_pixel(c);
XSetForeground(display, LW.gc, rcol);
XFillArc(display, LW.p, LW.gc, p.x-3, p.y-3, 3, 3, 23040, 23040);
}
}
LW.redraw();
}
void IFSGui::draw_2d_limit() {
Widget& LW = W_limit_plot;
//clear the limit widget
XSetForeground(display, LW.gc, WhitePixel(display, screen));
XFillRectangle(display, LW.p, LW.gc, 0, 0, LW.width, LW.height);
XSetForeground(display, LW.gc, BlackPixel(display, screen));
XDrawRectangle(display, LW.p, LW.gc, 0, 0, LW.width-1, LW.height-1);
XSetFillStyle(display, LW.gc, FillSolid);
//set up the IFS and get the initial rectangle
double rz = std::real(IFS.z);
if (rz < 0.6 || rz > 0.68) {
LW.redraw();
return;
}
ifs2d IFS2d;
IFS2d.gens.resize(2);
IFS2d.gens[0] = AffineMap( rz, 0, 1, rz, 0, 0 );
IFS2d.gens[1] = AffineMap( rz, 0, 1, rz, 1-rz, -1 );
double box_sizes[17] = {1.98593, 2.08085, 2.1883, 2.31103, 2.45263, 2.61793, 2.81353,
3.04875, 3.33714, 3.69922, 4.16762, 4.79755, 5.69039, 7.05483,
9.46713, 14.6384, 33.0532};
int ub_ind = 0;
double upper_bound = 0.6;
while (upper_bound < rz) {
upper_bound += 0.005;
ub_ind++;
};
double bs = box_sizes[ub_ind];
std::vector<Point2d<double> > initial_box(4);
initial_box[0] = Point2d<double>(0.5-bs, 0-bs);
initial_box[1] = Point2d<double>(0.5+bs, 0-bs);
initial_box[2] = Point2d<double>(0.5+bs, 0+bs);
initial_box[3] = Point2d<double>(0.5-bs, 0+bs);
//figure out where the box goes, as averages of its own boundary points,
//under all the words of length 6
std::vector<std::vector<Point4d<double> > > targets_under_words(64);
//std::cout << "Original box: " << initial_box[0] << " " << initial_box[1] << " " << initial_box[2] << " " << initial_box[3] << "\n";
for (int i=0; i<64; ++i) {
AffineMap A = IFS2d.semigroup_element(i, 6);
targets_under_words[i].resize(4);
//std::cout << i << ": box points: ";
for (int j=0; j<4; ++j) {
Point2d<double> point_target = A(initial_box[j]);
targets_under_words[i][j] = point_as_weighted_average_in_box(point_target, Point2d<double>(0.5,0), bs);
//std::cout << point_target << " weights: " << targets_under_words[i][j] << "; ";
}
//std::cout << "\n";
}
Point4d<double> zero_weights = point_as_weighted_average_in_box(Point2d<double>(0,0), Point2d<double>(0.5,0), bs);
//set the colors
int bcolor = get_rgb_color(0,0,1);
int rcolor = get_rgb_color(1,0,0);
std::vector< Box_Stuff > stack(1);
stack[0] = Box_Stuff(false, -1, 0, 0, initial_box);
while ((int)stack.size() > 0) {
Box_Stuff bs = stack.back();
stack.pop_back();
//if the box is disjoint from the window, get rid of it
if (!bs.contained && bs.is_disjoint(cpx(limit_ll.real(), 5*limit_ll.imag()),
cpx(limit_ur.real(), 5*limit_ur.imag())) ) continue;
//if we are at our target depth, draw it
if (bs.depth >= limit_depth) {
//XPoint v[4];
//for (int i=0; i<(int)4; ++i) {
// Point2d<int> pv = limit_cpx_to_pixel(cpx(bs.box[i].x, bs.box[i].y/5.0));
// v[i].x = pv.x; v[i].y = pv.y;
//}
//XSetForeground(display, LW.gc, (bs.last_gen == 1 ? rcolor : bcolor));
//XFillPolygon(display, LW.p, LW.gc, v, 4, Convex, CoordModeOrigin);
XSetForeground(display, LW.gc, (bs.last_gen == 1 ? rcolor : bcolor));
Point2d<double> zero_image = zero_weights.x*bs.box[0] + zero_weights.y*bs.box[1] +
zero_weights.z*bs.box[2] + zero_weights.w*bs.box[3];
Point2d<int> pv = limit_cpx_to_pixel(cpx(zero_image.x, zero_image.y/5.0));
XDrawPoint(display, LW.p, LW.gc, pv.x, pv.y);
//std::cout << "Drew: " << std::bitset<64>(bs.word).to_string() << "\n";
continue;
}
//if the box isn't disjoint, we must subdivide
//we check if it is contained in order to speed this up
for (int i=0; i<64; ++i) {
std::vector<Point2d<double> > new_box(4);
for (int j=0; j<4; ++j) {
Point4d<double> target_weights = targets_under_words[i][j];
new_box[j] = target_weights.x*bs.box[0] + target_weights.y*bs.box[1] +
target_weights.z*bs.box[2] + target_weights.w*bs.box[3];
}
if (bs.contained) {
stack.push_back( Box_Stuff(true,
(bs.last_gen==-1 ? (i>>5)&1 : bs.last_gen),
(bs.last_gen==-1 ? i : (bs.word<<6)|i),
bs.depth+1,
new_box) );
} else {
stack.push_back( Box_Stuff( bs.is_contained(cpx(limit_ll.real(), 5*limit_ll.imag()),
cpx(limit_ur.real(), 5*limit_ur.imag())),
(bs.last_gen==-1 ? (i>>5)&1 : bs.last_gen),
(bs.last_gen==-1 ? i : (bs.word<<6)|i),
bs.depth+1,
new_box) );
}
}
}
LW.redraw();
}
void IFSGui::draw_limit() {
double min_r;
if (!IFS.minimal_enclosing_radius(min_r)) {
return;
}
if (limit_nifs) {
draw_nifs_limit();
return;
} else if (limit_2d) {
draw_2d_limit();
return;
} else if (limit_gifs) {
draw_gifs_limit();
return;
}
Widget& LW = W_limit_plot;
//clear the limit widget
XSetForeground(display, LW.gc, WhitePixel(display, screen));
XFillRectangle(display, LW.p, LW.gc, 0, 0, LW.width, LW.height);
XSetForeground(display, LW.gc, BlackPixel(display, screen));
XDrawRectangle(display, LW.p, LW.gc, 0, 0, LW.width-1, LW.height-1);
XSetFillStyle(display, LW.gc, FillSolid);
int blue_color = (limit_uv_graph ? get_rgb_color(0.5,0.9,1) : get_rgb_color(0,0.6,1.0));
int yellow_color = (limit_uv_graph ? get_rgb_color(1,0.8,0.5) : get_rgb_color(1.0,0.6,0));
Ball initial_ball(0.5,(IFS.z-1.0)/2.0,(1.0-IFS.w)/2.0,min_r);
std::vector<std::pair<bool,Ball> > stack(0);
stack.push_back(std::make_pair(false, initial_ball));
while (stack.size() > 0) {
std::pair<bool,Ball> b = stack.back();
stack.pop_back();
//if the ball is disjoint from the window, we might as well
//get rid of it
if (!b.first && b.second.is_disjoint(limit_ll, limit_ur)) continue;
if ( (!limit_auto_depth && b.second.word_len >= limit_depth) ||
(limit_auto_depth && b.second.radius < limit_pixel_width/2.0) ) {
Point2d<int> p = limit_cpx_to_pixel(b.second.center);
double r = b.second.radius / limit_pixel_width;
if (r <= 1.0) r = 1.0;
if (limit_colors) {
XSetForeground(display, LW.gc, (b.second.last_gen_index()==0 ? blue_color : yellow_color));
}
if (limit_chunky) {
XFillArc(display, LW.p, LW.gc, p.x-r, p.y-r, int(2.0*r), int(2.0*r), 23040, 23040);
} else {
XDrawPoint(display, LW.p, LW.gc, p.x, p.y);
}
continue;
}
//if the ball isn't disjoint from the window, maybe it is contained in it?
Ball bz = IFS.act_on_right(0, b.second);
Ball bw = IFS.act_on_right(1, b.second);
if (b.first) {
stack.push_back(std::make_pair(true, bz));
stack.push_back(std::make_pair(true, bw));
} else {
if (b.second.is_contained(limit_ll, limit_ur)) {
stack.push_back(std::make_pair(true, bz));
stack.push_back(std::make_pair(true, bw));
} else {
stack.push_back(std::make_pair(false, bz));
stack.push_back(std::make_pair(false, bw));
}
}
}
//draw the marked points 0, 1/2, 1
for (int i=0; i<(int)limit_marked_points.size(); ++i) {
cpx& c = limit_marked_points[i];
int rcol = get_rgb_color(1,0.1,0);
if (limit_ll.real() < c.real() && c.real() < limit_ur.real() &&
limit_ll.imag() < c.imag() && c.imag() < limit_ur.imag()) {
Point2d<int> p = limit_cpx_to_pixel(c);
XSetForeground(display, LW.gc, rcol);
XFillArc(display, LW.p, LW.gc, p.x-3, p.y-3, 3, 3, 23040, 23040);
}
}
//draw the uv graph
if (limit_uv_graph) {
//generate all the balls of the given depth
std::stringstream T; T.str("");
std::vector<Ball> uv_graph_balls;
std::vector<Point3d<int> > uv_graph_edges; //(i,j,k) records an edge between i and j which swaps a suffix of length k
IFS.compute_uv_graph(uv_graph_edges, uv_graph_balls, limit_uv_graph_depth, 0);
//get the size of a text string of this length
XFontStruct* font = XLoadQueryFont(display, "fixed");
XCharStruct te;
int fdir, fdescent, fascent;
T << Bitword(uv_graph_balls[0].word, uv_graph_balls[0].word_len);
XTextExtents(font, T.str().c_str(), T.str().size(), &fdir, &fascent, &fdescent, &te);
int text_width_offset = (te.rbearing - te.lbearing)/2;
int text_height_offset = (te.ascent - te.descent)/2;
//draw the balls
XSetForeground(display, LW.gc, BlackPixel(display, screen));
double r = 15;
for (int i=0; i<(int)uv_graph_balls.size(); ++i) {
cpx& c = uv_graph_balls[i].center;
if (c.real() < limit_ll.real() ||
c.real() > limit_ur.real() ||
c.imag() < limit_ll.imag() ||
c.imag() > limit_ur.imag()) {
continue;
}
Point2d<int> p = limit_cpx_to_pixel(c);
//double r = uv_graph_balls[i].radius / limit_pixel_width;
T.str(""); T << Bitword(uv_graph_balls[i].word, uv_graph_balls[i].word_len);
XDrawArc(display, LW.p, LW.gc, p.x-r, p.y-r, int(2*r), int(2*r), 23040, 23040);
XDrawString(display, LW.p, LW.gc, p.x-text_width_offset, p.y+text_height_offset, T.str().c_str(), T.str().size());
}
//draw the edges
T.str("8");
XTextExtents(font, T.str().c_str(), T.str().size(), &fdir, &fascent, &fdescent, &te);
text_width_offset = (te.rbearing - te.lbearing)/2;
text_height_offset = (te.ascent - te.descent)/2;
XSetLineAttributes(display, LW.gc, 1, LineSolid, 1, 1);
for (int i=0; i<(int)uv_graph_edges.size(); ++i){
Point3d<int>& e = uv_graph_edges[i];
cpx& cc1 = uv_graph_balls[e.x].center;
cpx& cc2 = uv_graph_balls[e.y].center;
if ((cc1.real() < limit_ll.real() ||
cc1.real() > limit_ur.real() ||
cc1.imag() < limit_ll.imag() ||
cc1.imag() > limit_ur.imag()) &&
(cc2.real() < limit_ll.real() ||
cc2.real() > limit_ur.real() ||
cc2.imag() < limit_ll.imag() ||
cc2.imag() > limit_ur.imag())) {
continue;
}
Point2d<int> c1 = limit_cpx_to_pixel(cc1);
Point2d<int> c2 = limit_cpx_to_pixel(cc2);
Point2d<float> v(c2.x-c1.x, c2.y-c1.y);
v = v/(float)sqrt(dot(v,v));
Point2d<float> c1p(c1.x + r*v.x, c1.y + r*v.y);
Point2d<float> c2p(c2.x - r*v.x, c2.y - r*v.y);
Point2d<float> perp(-10*v.y, 10*v.x);
Point2d<float> text_center = Point2d<float>((c1p.x + c2p.x)/2.0, (c1p.y + c2p.y)/2.03);
text_center = text_center + perp;
T.str(""); T << e.z;
XDrawString(display, LW.p, LW.gc, text_center.x-text_width_offset, text_center.y+text_height_offset, T.str().c_str(), T.str().size());
XDrawLine(display, LW.p, LW.gc, c1p.x, c1p.y, c2p.x, c2p.y);
}
}
LW.redraw();
}
void IFSGui::recenter_limit(cpx c) {
double radius = (limit_ur.real() - limit_ll.real())/2.0;
limit_ll = c - cpx(radius, radius);
limit_ur = c + cpx(radius, radius);
draw_limit();
}
cpx IFSGui::mand_pixel_group_to_cpx(const Point2d<int>& p) {
double r = (p.x + 0.5)*mand_pixel_group_width + mand_ll.real();
double i = mand_ur.imag() - (p.y + 0.5)*mand_pixel_group_width;
return cpx(r,i);
}
Point2d<int> IFSGui::mand_cpx_to_pixel_group(const cpx& c) {
return Point2d<int>( (c.real() - mand_ll.real()) / mand_pixel_group_width,
mand_num_pixel_groups - ((c.imag() - mand_ll.imag())/ mand_pixel_group_width) );
}
cpx IFSGui::mand_pixel_to_cpx(const Point2d<int>& p) {
double r = (p.x + 0.5)*mand_pixel_width + mand_ll.real();
double i = mand_ur.imag() - (p.y + 0.5)*mand_pixel_width;
return cpx(r,i);
}
Point2d<int> IFSGui::mand_cpx_to_pixel(const cpx& c) {
return Point2d<int>( (c.real() - mand_ll.real()) / mand_pixel_width,
W_mand_plot.height - ((c.imag() - mand_ll.imag()) / mand_pixel_width) );
}
int IFSGui::mand_get_color(PointNd<6,int>& p) {
/*
if (mand_trap && p.z > 0) { //use the trap color
return p.z;
} else if (mand_set_C && p[4] > 0) {
return p[4];
} else if (mand_connected && p.x >= 0) {
return p.x*0x000001;
} else if (mand_contains_half && p.y > 0) {
return p.y;
} else if (mand_dirichlet && p.w >= 0) {
return p.w;
} else {
return WhitePixel(display, screen);
}
*/
if (mand_trap && p.z > 0) { //use the trap color
return p.z;
} else if (mand_set_C && p[4] > 0) {
return p[4];
} else if (mand_contains_half && p.y > 0) {
return p.y;
} else if (mand_theta && p[5] > 0) {
return p[5];
} else if (mand_connected && p.x >= 0) {
return p.x*0x000001;
} else if (mand_dirichlet && p.w >= 0) {
return p.w;
} else {
return WhitePixel(display, screen);
}
}
void IFSGui::mand_draw_ball(const Ball& b, int col) {
Point2d<int> p = mand_cpx_to_pixel(b.center);
Widget& MP = W_mand_plot;
XSetForeground(display, MP.gc, col);
int r = int(b.radius / mand_pixel_width);
if (r < 2) r = 2;
XFillArc(display, MP.p, MP.gc, p.x-r, p.y-r, 2*r, 2*r, 23040, 23040);
XCopyArea(display, MP.p, main_window, MP.gc, p.x-r, p.y-r, 2*r,2*r, MP.ul.x+p.x-r, MP.ul.y+p.y-r);
}
//draw the mandelbrot set
void IFSGui::draw_mand() {
ifs temp_IFS;
Widget& MW = W_mand_plot;
//set up the TLB
std::vector<Ball> TLB;
double TLB_C,TLB_Z;
bool found_TLB = false;
if (mand_trap && !mand_grid_trap_valid) {
//std::cout << "About to find TLB\n";
temp_IFS.set_params(IFS.z, IFS.z);
temp_IFS.TLB_for_region(TLB, mand_ll, mand_ur, 16, &TLB_C, &TLB_Z, 0);
found_TLB = (TLB.size() != 0);
}
//set up the dirichlet stuff
std::map<std::set<std::pair<Bitword,Bitword> >, int> sets_to_colors;
std::map<std::set<std::pair<Bitword,Bitword> >, int>::iterator it;
for (int i=0; i<(int)mand_num_pixel_groups; ++i) {
for (int j=0; j<(int)mand_num_pixel_groups; ++j) {
//do the necessary computations
cpx c = mand_pixel_group_to_cpx(Point2d<int>(i,j));
temp_IFS.set_params(c,c);
if (mand_connected && !mand_grid_connected_valid) {
//temp_IFS.set_params(c*c,c*c);
if (true) { //!limit_nifs && !limit_gifs) {
if (!temp_IFS.is_connected(mand_connected_depth, mand_data_grid[i][j].x) ) {
mand_data_grid[i][j].x = -1;
}
} else if (limit_nifs) {
nIFS nifs(3, c);
nifs.centers[0] = -1; nifs.centers[1] = 0; nifs.centers[2] = 1;
if (!nifs.is_connected(mand_connected_depth, mand_data_grid[i][j].x)) {
mand_data_grid[i][j].x = -1;
}
} else if (limit_gifs) {
//create the gifs object
double PI = 3.14159265358979323846;
std::vector<cpx> cs(4);
std::vector<cpx> fs(4);
cs[0] = cpx(0,1.0);
cs[1] = cpx(-sin(PI/3.0), -cos(PI/3.0));
cs[2] = cpx(sin(PI/3.0), -cos(PI/3.0));
cs[3] = cpx(0,0);
fs[0] = c.real(); fs[1] = c.real(); fs[2] = c.real();
fs[3] = c.imag();
gIFS gifs(fs,cs);
if (!gifs.is_connected(mand_connected_depth, mand_data_grid[i][j].x)) {
mand_data_grid[i][j].x = -1;
}
}
}
if (mand_contains_half && !mand_grid_contains_half_valid) {
//temp_IFS.set_params(sqrt(c), sqrt(c));
if (temp_IFS.contains_half(mand_contains_half_depth, mand_data_grid[i][j].y)) {
mand_data_grid[i][j].y = get_rgb_color(0.5, double(mand_data_grid[i][j].y)/100, 0.5);
} else {
mand_data_grid[i][j].y = -1;
}
//temp_IFS.set_params(c,c);
}
if (mand_trap && !mand_grid_trap_valid && found_TLB) {
double trap_radius;
int multiplier = 100/mand_trap_depth;
int diff;
if (mand_limit_trap) {
diff = multiplier*temp_IFS.check_limit_TLB_recursive(TLB, &TLB_C, &TLB_Z, trap_radius, NULL, mand_trap_depth);
} else {
diff = multiplier*temp_IFS.check_TLB(TLB,NULL,NULL,trap_radius,NULL,mand_trap_depth);
}
mand_data_grid[i][j].z = (diff < 0 ? -1 : get_rgb_color(0, double(diff)/100, 1.0));
}
if (mand_dirichlet &&
(!mand_connected || mand_data_grid[i][j].x == -1) &&
(!mand_grid_dirichlet_valid || mand_data_grid[i][j].w == -1)) {
std::vector<std::pair<Bitword,Bitword> > uv_words;
temp_IFS.find_closest_uv_words(uv_words, mand_dirichlet_depth, 0.00000001,4097);
std::set<std::pair<Bitword,Bitword> > uv_words_set(uv_words.begin(), uv_words.end());
it = sets_to_colors.find(uv_words_set);
if (it == sets_to_colors.end()) { //need to add a new color
//double r = 0.5*((double)rand()/(double)RAND_MAX) + 0.5;
//mand_data_grid[i][j].w = (uv_words.size() == 1 ? get_rgb_color(0, r, r) : get_rgb_color(r, 0, 0) );
double r = 1.0/(1+2*log2((double)uv_words.size()));
mand_data_grid[i][j].w = get_rgb_color(r, r, r);
sets_to_colors[uv_words_set] = mand_data_grid[i][j].w;
} else {
mand_data_grid[i][j].w = it->second;
}
}
if (mand_set_C && !mand_grid_set_C_valid) {
if (temp_IFS.close_to_set_C(mand_set_C_depth,
0.707107*mand_pixel_group_width)) {
mand_data_grid[i][j][4] = get_rgb_color(1.0,0.0,1.0);
}
}
if (mand_theta && !mand_grid_theta_valid) {
double th, lam;
if (temp_IFS.compute_coordinates(&th, &lam, mand_theta_depth)) {
mand_data_grid[i][j][5] = (int)((th+0.6)*100000.0);
} else {
mand_data_grid[i][j][5] = -1;
}
}
//draw the pixel for the impatient
int col = mand_get_color(mand_data_grid[i][j]);
XSetForeground(display, MW.gc, col);
XFillRectangle(display, MW.p, MW.gc, i*mand_pixel_group_size,
j*mand_pixel_group_size,
mand_pixel_group_size,
mand_pixel_group_size);
XCopyArea(display, MW.p, main_window, MW.gc, i*mand_pixel_group_size,
j*mand_pixel_group_size,
mand_pixel_group_size,
mand_pixel_group_size,
MW.ul.x + i*mand_pixel_group_size,
MW.ul.y + j*mand_pixel_group_size);
}
}
//if we're drawing theta, we need to go back over and get the real values
if (mand_theta && !mand_grid_theta_valid) {
int min_theta=-1;
int max_theta=-1;
for (int i=0; i<(int)mand_num_pixel_groups; ++i) {
for (int j=0; j<(int)mand_num_pixel_groups; ++j) {
if (mand_data_grid[i][j][5] > 0) {
if (min_theta==-1 || mand_data_grid[i][j][5] < min_theta)
min_theta = mand_data_grid[i][j][5];
if (max_theta==-1 || mand_data_grid[i][j][5] > max_theta)
max_theta = mand_data_grid[i][j][5];
}
}
}
int theta_range = double(max_theta - min_theta);
for (int i=0; i<(int)mand_num_pixel_groups; ++i) {
for (int j=0; j<(int)mand_num_pixel_groups; ++j) {
int v = mand_data_grid[i][j][5];
if (v > 0) {
double amount = double((v-min_theta)%(theta_range/30)) / double(theta_range/30) ;
mand_data_grid[i][j][5] = get_rgb_color( 1, amount, amount );
}
int col = mand_get_color(mand_data_grid[i][j]);
XSetForeground(display, MW.gc, col);
XFillRectangle(display, MW.p, MW.gc, i*mand_pixel_group_size,
j*mand_pixel_group_size,
mand_pixel_group_size,
mand_pixel_group_size);
XCopyArea(display, MW.p, main_window, MW.gc, i*mand_pixel_group_size,
j*mand_pixel_group_size,
mand_pixel_group_size,
mand_pixel_group_size,
MW.ul.x + i*mand_pixel_group_size,
MW.ul.y + j*mand_pixel_group_size);
}
}
}
if (mand_connected && !mand_grid_connected_valid) mand_grid_connected_valid = true;
if (mand_contains_half && !mand_grid_contains_half_valid) mand_grid_contains_half_valid = true;
if (mand_trap && !mand_grid_trap_valid) mand_grid_trap_valid = true;
if (mand_dirichlet && !mand_grid_dirichlet_valid) mand_grid_dirichlet_valid = true;
if (mand_set_C && !mand_grid_set_C_valid) mand_grid_set_C_valid = true;
if (mand_theta && !mand_grid_theta_valid) mand_grid_theta_valid = true;
//now draw the highlighted point
Point2d<int> h = mand_cpx_to_pixel(IFS.z);
int rcol = get_rgb_color(1.0,0.1,0.0);
XSetForeground(display, MW.gc, rcol);
XFillArc(display, MW.p, MW.gc, h.x-2, h.y-2, 4, 4, 23040, 23040);
//now draw the path, if there is one
if (path.is_valid) {
int rcol = get_rgb_color(1,0.2,1);
XSetForeground(display, MW.gc, rcol);
for (int i=0; i<(int)path.path.size()-1; ++i) {
Point2d<int> p1 = mand_cpx_to_pixel(path.path[i]);
Point2d<int> p2 = mand_cpx_to_pixel(path.path[i+1]);
XDrawLine(display, MW.p, MW.gc, p1.x, p1.y, p2.x, p2.y);
}
if (path.closed) {
Point2d<int> p1 = mand_cpx_to_pixel(path.path[path.path.size()-1]);
Point2d<int> p2 = mand_cpx_to_pixel(path.path[0]);
XDrawLine(display, MW.p, MW.gc, p1.x, p1.y, p2.x, p2.y);
}
//if the path has traps, draw them
if (path.has_traps) {
for (int i=0; i<(int)path.traps.size(); ++i) {
XSetForeground(display, MW.gc, path.trap_colors[i]);
Point2d<int> p = mand_cpx_to_pixel(path.traps[i].center);
int r = int(path.traps[i].radius / mand_pixel_width);
if (r < 2) r = 2;
XFillArc(display, MW.p, MW.gc, p.x-r, p.y-r, 2*r, 2*r, 23040, 23040);
}
}
//if the path has half balls, draw them
//if (path.has_half_words) {
// IFS.certify_set_B_path(path.path, limit_depth, 1);
//}
if (path.has_half_words) {
std::vector<std::vector<Ball> > subdivided_balls(0);
int i=path.half_start;
int num_done = 0;
int total_num = path.half_words.size();
int num_to_do = (path.half_end >= path.half_start ?
path.half_end - path.half_start+1 :
(path.half_end+1) + (path.half_words.size()-path.half_start));
std::cout << "Num to do: " << num_to_do << "\n";
do {
//find the balls
subdivided_balls.push_back( IFS.subdivide_half_prefix(path.half_words[i],
path.path[0],
path.half_depth,
mand_ll, mand_ur) );
std::cout.flush();
//draw the balls
int sbs = subdivided_balls.back().size();
std::cout << "Got the " << sbs << " balls -- about to draw\n";
int col = get_rgb_color(0, (double)i/(double)total_num,
(double)(total_num-i)/(double)total_num);
std::cout << "Got color " << col << "\n";
XSetForeground(display, MW.gc, col);
for (int j=0; j<(int)subdivided_balls.back().size(); ++j) {
if (j==0) {
std::cout << "Drawing ball at " << subdivided_balls.back()[j].center << " of radius " << subdivided_balls.back()[j].radius <<
" with ll " << mand_ll << " ur " << mand_ur << " pixel width: " << mand_pixel_width << " so pixel radius = " << int(subdivided_balls.back()[j].radius / mand_pixel_width) << "\n";
std::cout.flush();
}
Point2d<int> p = mand_cpx_to_pixel(subdivided_balls.back()[j].center);
int r = int(subdivided_balls.back()[j].radius / mand_pixel_width);
if (r < 2) r = 2;
XFillArc(display, MW.p, MW.gc, p.x-r, p.y-r, 2*r, 2*r, 23040, 23040);
}
MW.redraw();
++i;
++num_done;
if (i == (int)path.half_words.size()) i = 0;
} while (num_done < num_to_do);
}
}
MW.redraw();
}
void IFSGui::change_highlighted_ifs(cpx c) {
//redraw the current red dot with the saved stuff
Widget& MW = W_mand_plot;
Point2d<int> p = mand_cpx_to_pixel(IFS.z);
int pg_i = (p.x/mand_pixel_group_size) - 2;
if (pg_i < 0) pg_i = 0;
int upper_limit_i = pg_i + 6;
if (upper_limit_i >= mand_num_pixel_groups) upper_limit_i = mand_num_pixel_groups-1;
int pg_j = (p.y/mand_pixel_group_size) - 2;
if (pg_j < 0) pg_j = 0;
int upper_limit_j = pg_j + 6;
if (upper_limit_j >= mand_num_pixel_groups) upper_limit_j = mand_num_pixel_groups-1;
for (int i=pg_i; i<upper_limit_i; ++i) {
for (int j=pg_j; j<upper_limit_j; ++j) {
int col = mand_get_color(mand_data_grid[i][j]);
XSetForeground(display, MW.gc, col);
XFillRectangle(display, MW.p, MW.gc, i*mand_pixel_group_size,
j*mand_pixel_group_size,
mand_pixel_group_size,
mand_pixel_group_size);
}
}
XCopyArea(display, MW.p, main_window, MW.gc, pg_i*mand_pixel_group_size,
pg_j*mand_pixel_group_size,
6*mand_pixel_group_size,
6*mand_pixel_group_size,
MW.ul.x + pg_i*mand_pixel_group_size,
MW.ul.y + pg_j*mand_pixel_group_size);
//now actually switch the point
IFS.set_params(c,c);
Point2d<int> h = mand_cpx_to_pixel(c);
int rcol = get_rgb_color(1.0,0.1,0.0);
XSetForeground(display, MW.gc, rcol);
XFillArc(display, MW.p, MW.gc, h.x-2, h.y-2, 5, 5, 23040, 23040);
XCopyArea(display, MW.p, main_window, MW.gc,h.x-2, h.y-2, 6, 6,
MW.ul.x + h.x-2, MW.ul.y + h.y-2);
if (window_mode != MANDELBROT) {
draw_limit();
}
recompute_point_data();
}
//this zooms on whatever the highlighted ifs is
void IFSGui::mand_zoom(double radius_multiplier) {
double radius = (mand_ur.real() - mand_ll.real())/2.0;
cpx c = IFS.z;
radius *= radius_multiplier;
mand_ll = c - cpx(radius, radius);
mand_ur = c + cpx(radius, radius);
mand_reset_mesh();
draw_mand();
}
//recenters on the highlighted ifs
void IFSGui::mand_recenter() {
double radius = (mand_ur.real() - mand_ll.real())/2.0;
cpx c = IFS.z;
mand_ll = c - cpx(radius, radius);
mand_ur = c + cpx(radius, radius);
mand_grid_connected_valid = false;
mand_grid_contains_half_valid = false;
mand_grid_trap_valid = false;
mand_grid_dirichlet_valid = false;
mand_grid_set_C_valid = false;
mand_grid_theta_valid = false;
draw_mand();
}
void IFSGui::mand_reset_mesh() {
mand_pixel_width = (mand_ur.real() - mand_ll.real()) / double(W_mand_plot.width);
mand_pixel_group_width = mand_pixel_group_size * mand_pixel_width;
mand_num_pixel_groups = W_mand_plot.width / mand_pixel_group_size;
mand_data_grid.resize(mand_num_pixel_groups);
for (int i=0; i<mand_num_pixel_groups; ++i) {
mand_data_grid[i] = std::vector<PointNd<6,int> >(mand_num_pixel_groups, PointNd<6,int>(-1));
}
mand_grid_connected_valid = false;
mand_grid_contains_half_valid = false;
mand_grid_trap_valid = false;
mand_grid_dirichlet_valid = false;
mand_grid_set_C_valid = false;
mand_grid_theta_valid = false;
}
void IFSGui::recompute_point_data() {
std::stringstream T;
T.precision(15);
int difficulty;
T.str(""); T << "Location: " << IFS.z;
W_point_point.update_text(T.str());
if (!point_connected_check) {
T.str(""); T << "(disabled)";
} else {
T.str("");
T << ( (point_is_connected = IFS.is_connected(point_connected_depth, difficulty)) ? "yes" : "no" );
}
W_point_connected_status.update_text(T.str());
if (!point_contains_half_check) {
T.str(""); T << "(disabled)";
} else {
T.str("");
T << ( (point_is_contains_half = IFS.contains_half(point_contains_half_depth, difficulty)) ? "yes" : "no" );
std::vector<Bitword> half_words;
IFS.half_balls(half_words, point_contains_half_depth, 4);
for (int i=0; i<(int)half_words.size(); ++i) {
std::cout << half_words[i];
double epsilon;
if (IFS.certify_set_B_point(half_words[i], true, epsilon)) {
std::cout << " (certified all within " << epsilon << ")\n";
} else {
std::cout << " (not certified)\n";
}
}
if (half_words.size() > 0) std::cout << "\n";
}
W_point_contains_half_status.update_text(T.str());
if (!point_uv_words_check) {
T.str(""); T << "(disabled)";
} else {
IFS.find_closest_uv_words(point_uv_words, point_uv_words_depth);
T.str("");
T << point_uv_words[0].first << " " << point_uv_words[0].second;
}
W_point_uv_words_status.update_text(T.str());
if (!point_trap_check) {
T.str(""); T << "(disabled)";
} else {
std::vector<Ball> TLB;
cpx box_ll = IFS.z - cpx(0.0000001, 0.0000001);
cpx box_ur = IFS.z + cpx(0.0000001, 0.0000001);
double TLB_Z,TLB_C;
T.str("");
if (!IFS.TLB_for_region(TLB, box_ll, box_ur, 15, &TLB_C, &TLB_Z, 0)) {
T << "Couldn't find TLB for box " << box_ll << " " << box_ur << " at depth " << 15;
} else {
double trap_radius;
std::vector<std::pair<Bitword,Bitword> > tw;
point_trap_words.resize(1);
int diff;
if (mand_limit_trap) {
diff = IFS.check_limit_TLB_recursive(TLB, &TLB_C, &TLB_Z,trap_radius,&tw,point_trap_depth);
} else {
diff = IFS.check_TLB(TLB, &TLB_C, &TLB_Z,trap_radius,&tw,point_trap_depth);
}
point_trap_words = tw;
if (diff < 0) {
T << "not found";
} else {
T << point_trap_words[0].first << " " << point_trap_words[0].second;
}
}
}
W_point_trap_status.update_text(T.str());
//std::cout << "Close to set C: ";
//if (IFS.close_to_set_C(mand_set_C_depth, 0.707107*mand_pixel_group_width)) {
// std::cout << "yes\n";
//} else {
// std::cout << "no\n";
//}
if (!point_coordinates_check) {
T.str(""); T << "(disabled)";
} else {
point_coordinates_theta = -1;
point_coordinates_lambda = -1;
(void) IFS.compute_coordinates(&point_coordinates_theta,
&point_coordinates_lambda,
point_coordinates_depth);
T.str("");
T << "Theta: " << point_coordinates_theta << " Lambda: " << point_coordinates_lambda;
}
W_point_coordinates_status.update_text(T.str());
}
void IFSGui::find_coordinates_along_path(int verbose) {
if (!path.is_valid || currently_drawing_path || path.path.size() == 0) return;
ifs temp_IFS;
path.coordinates.resize(0);
for (int i=0; i<(int)path.path.size(); ++i) {
temp_IFS.set_params(path.path[i], path.path[i]);
double t1, ell1;
double t2, ell2;
if (temp_IFS.compute_coordinates( &t1, &ell1, mand_theta_depth ) &&
temp_IFS.compute_coordinates( &t2, &ell2, mand_theta_depth+1) ) {
if (abs(t1) < 1 && abs(t2) < 1 && abs(ell1) < 3 && abs(ell2) < 3) {
path.coordinates.push_back( std::make_pair( 0.5*(t1+t2), 0.5*(ell1+ell2)) );
}
}
}
for (int i=0; i<(int)path.coordinates.size(); ++i) {
std::cout << "{" << path.coordinates[i].first << "," <<
path.coordinates[i].second << "},";
}
std::cout << "\n";
}
void IFSGui::find_traps_along_path(int verbose) {
if (!path.is_valid || currently_drawing_path || path.path.size() == 0) return;
//find the extents of the path, plus a little extra
cpx box_ll = path.path[0];
cpx box_ur = path.path[0];
for (int i=0; i<(int)path.path.size(); ++i) {
if (path.path[i].real() < box_ll.real()) {
box_ll = cpx(path.path[i].real(), box_ll.imag());
}
if (path.path[i].real() > box_ur.real()) {
box_ur = cpx(path.path[i].real(), box_ur.imag());
}
if (path.path[i].imag() < box_ll.imag()) {
box_ll = cpx(box_ll.real(), path.path[i].imag());
}
if (path.path[i].imag() > box_ur.real()) {
box_ur = cpx(box_ur.real(), path.path[i].imag());
}
}
double bw = box_ur.real() - box_ll.real();
double bh = box_ur.imag() - box_ll.imag();
box_ur = box_ur + cpx(0.1*bw, 0.1*bh);
box_ll = box_ll - cpx(0.1*bw, 0.1*bh);
cpx av = (box_ll + box_ur)/2.0;
//find the TLB for this region
std::vector<Ball> TLB;
ifs temp_IFS;
double TLB_C, TLB_Z;
temp_IFS.set_params(av, av);
if (!temp_IFS.TLB_for_region(TLB, box_ll, box_ur, 15, &TLB_C, &TLB_Z, verbose)) {
std::cout << "Couldn't find TLB for box " << box_ll << " " << box_ur << " at depth " << mand_trap_depth << "\n";
return;
}
if (verbose>0) {
std::cout << "Got the TLB constants: " << TLB_C << " " << TLB_Z << "\n";
}
//find traps along all the path segments
path.traps.resize(0);
path.trap_colors.resize(0);
path.has_traps = true;
int upper_index_bound = (path.closed ? path.path.size()-1 : path.path.size()-2);
for (int i=0; i<=upper_index_bound; ++i) {
int ip1 = (i == (int)path.path.size()-1 ? 0 : i+1);
cpx current_z = path.path[i];
cpx end_z = path.path[ip1];
if (verbose>0) {
std::cout << "Finding traps along segment " << current_z << " - " << end_z << "\n";
}
do {
double epsilon = -1;
int difficulty = -1;
temp_IFS.set_params(current_z, current_z);
if (mand_limit_trap) {
difficulty = temp_IFS.check_limit_TLB_recursive(TLB, &TLB_C, &TLB_Z, epsilon, NULL, mand_trap_depth);
} else {
difficulty = temp_IFS.check_TLB(TLB, &TLB_C, &TLB_Z, epsilon, NULL, mand_trap_depth);
}
if ( difficulty < 0 ) {
std::cout << "Failed to find trap at " << current_z << "\n";
return;
}
if (verbose>0) {
std::cout << "Found trap " << current_z << " - " << epsilon << "\n";
}
path.traps.push_back(Ball(current_z, epsilon));
double gamount = double(difficulty)/double(mand_trap_depth);
path.trap_colors.push_back( get_rgb_color(0.5,gamount,1) );
cpx v = end_z-current_z;
current_z = current_z + epsilon*(v/abs(v));
//draw it to show what's happening
mand_draw_ball(path.traps.back(), path.trap_colors.back());
} while ( abs(path.traps.back().center - end_z) >= path.traps.back().radius );
}
}
/****************************************************************************
* main gui functions
****************************************************************************/
void IFSGui::pack_widget_upper_right(const Widget* w1, Widget* w2) {
//figure out where it can go
int desired_x,desired_y;
if (w1 != NULL) {
desired_x = w1->ul.x + w1->width;
desired_y = w1->ul.y;
} else {
desired_x = 0;
desired_y = 0;
}
//std::cout << "Packing widget of size " << w2->width << " " << w2->height << "\n";
//std::cout << "Desired x: " << desired_x << "\n";
//go through and check the other widgets to see how
//far down they obstruct this one
int greatest_y_obstruction = 0;
for (int i=0; i<(int)widgets.size(); ++i) {
if (widgets[i] == w1) continue;
if (widgets[i]->ul.x == desired_x &&
widgets[i]->ul.y + widgets[i]->height > greatest_y_obstruction) {
greatest_y_obstruction = widgets[i]->ul.y + widgets[i]->height;
//std::cout << "Found widget " << i << " obstructs to height " << greatest_y_obstruction << "\n";
}
}
if (greatest_y_obstruction + w2->height > main_window_height) {
//std::cout << "Cannot pack widget -- too tall\n";
return;
}
int y = (desired_y > greatest_y_obstruction ? desired_y : greatest_y_obstruction);
//now determine whether we have to shove it over to make room
int greatest_x_obstruction = desired_x;
for (int i=0; i<(int)widgets.size(); ++i) {
if (widgets[i]->ul.y + widgets[i]->height > y &&
widgets[i]->ul.y < y + w2->height &&
widgets[i]->ul.x + widgets[i]->width > greatest_x_obstruction) {
greatest_x_obstruction = widgets[i]->ul.x + widgets[i]->width;
}
}
int x = greatest_x_obstruction;
//find the position
w2->ul = Point2d<int>(x, y);
//std::cout << "Packed widget at " << w2->ul << "\n";
//record it in the list of widgets
widgets.push_back(w2);
}
void IFSGui::detach_widget(Widget* w) {
for (int i=0; i<(int)widgets.size(); ++i) {
if (widgets[i] == w) {
widgets.erase(widgets.begin()+i);
break;
}
}
w->clear();
}
int IFSGui::get_rgb_color(double r, double g, double b) {
XColor temp;
temp.flags = DoRed | DoGreen | DoBlue;
temp.red = (int)(r*65535);
temp.green = (int)(g*65535);
temp.blue = (int)(b*65535);
if (XAllocColor(display, DefaultColormap(display, screen), &temp) == 0) {
std::cout << "Color not found?\n";
}
return temp.pixel;
}
void IFSGui::reset_and_pack_window() {
//destroy the main window, if it exists
if (main_window_initialized) {
XDestroyWindow(display, main_window);
}
//figure out how big to make the window (here ss = sidebar size)
//for each of limit and mandelbrot, we need height x+ss and width x+ss,
//if if it's just one of them, we can set the height to be the display height
//minus 200 (say), as long as x+ss is smaller than the width
//otherwise, we can make it x+ss, as long as 2x+ss < width
int display_width = XDisplayWidth(display, screen);
int display_height = XDisplayHeight(display, screen);
int ss = (limit_sidebar_size > mand_sidebar_size ? limit_sidebar_size : mand_sidebar_size);
int width_rest = (window_mode == BOTH ? (display_width-2*ss)/2 :
display_width - ss );
int height_rest = display_height - 170;
int x = (width_rest > height_rest ? height_rest : width_rest);
if (window_mode == MANDELBROT) {
main_window_height = x + 140;
main_window_width = x + mand_sidebar_size;
} else if (window_mode == LIMIT) {
main_window_height = x + 140;
main_window_width = x + limit_sidebar_size;
} else {
main_window_height = x + 140;
main_window_width = 2*x + mand_sidebar_size + limit_sidebar_size;
}
//compute the widths
limit_pixel_width = (limit_ur.real() - limit_ll.real())/double(x);
//create the window
main_window = XCreateSimpleWindow(display,
RootWindow(display, screen), 20, 20,
main_window_width, main_window_height, 4,
BlackPixel(display, screen), WhitePixel(display, screen));
XSelectInput(display, main_window, ExposureMask |
PointerMotionMask |
KeyPressMask |
ButtonPressMask |
ButtonReleaseMask );
XMapWindow(display, main_window);
//wait until the window is actually mapped
while (true) {
XEvent e;
XNextEvent(display, &e);
if (e.type == Expose) break;
}
main_window_initialized = true;
//create the buttons and stuff and pack them
widgets.resize(0);
//used to fill the text
std::stringstream T;
//stuff for the IFS computations
W_switch_to_limit = WidgetButton(this, "Switch to limit", -1, 20, &IFSGui::S_switch_to_limit);
W_switch_to_mandelbrot = WidgetButton(this, "Switch to mandelbrot", -1,20, &IFSGui::S_switch_to_mandelbrot);
W_switch_to_combined = WidgetButton(this, "Switch to combined", -1, 20, &IFSGui::S_switch_to_combined);
W_point_title = WidgetText(this, "Current IFS status:", -1, 20);
W_point_point = WidgetText(this, "Location: initializing", 500, 20);
W_point_connected_check = WidgetCheck(this, "Connectedness", 105, 20, point_connected_check, &IFSGui::S_point_connected);
W_point_connected_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_point_connected_decrease_depth);
T.str(""); T << point_connected_depth;
W_point_connected_depth_label = WidgetText(this, T.str(), -1, 20);
W_point_connected_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_point_connected_increase_depth);
W_point_connected_status = WidgetText(this, "initializing", -1, 20);
W_point_contains_half_check = WidgetCheck(this, "Contains 1/2", 105, 20, point_contains_half_check, &IFSGui::S_point_contains_half);
W_point_contains_half_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_point_contains_half_decrease_depth);
T.str(""); T << point_contains_half_depth;
W_point_contains_half_depth_label = WidgetText(this, T.str(), -1, 20);
W_point_contains_half_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_point_contains_half_increase_depth);
W_point_contains_half_status = WidgetText(this, "initializing", -1, 20);
W_point_uv_words_check = WidgetCheck(this, "uv words", 105, 20, point_uv_words_check, &IFSGui::S_point_uv_words);
W_point_uv_words_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_point_uv_words_decrease_depth);
T.str(""); T << point_uv_words_depth;
W_point_uv_words_depth_label = WidgetText(this, T.str(), -1, 20);
W_point_uv_words_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_point_uv_words_increase_depth);
W_point_uv_words_status = WidgetText(this, "initializing", x, 20);
W_point_trap_check = WidgetCheck(this, "Trap", 105, 20, point_trap_check, &IFSGui::S_point_trap);
W_point_trap_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_point_trap_decrease_depth);
T.str(""); T << point_trap_depth;
W_point_trap_depth_label = WidgetText(this, T.str(), -1, 20);
W_point_trap_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_point_trap_increase_depth);
W_point_trap_status = WidgetText(this, "initializing", x, 20);
W_point_coordinates_check = WidgetCheck(this, "Coordinates", 105, 20, point_coordinates_check, &IFSGui::S_point_coordinates);
W_point_coordinates_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_point_coordinates_decrease_depth);
T.str(""); T << point_coordinates_depth;
W_point_coordinates_depth_label = WidgetText(this, T.str(), -1, 20);
W_point_coordinates_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_point_coordinates_increase_depth);
W_point_coordinates_status = WidgetText(this, "initializing", x, 20);
//if the limit set is shown:
if (window_mode != MANDELBROT) {
W_limit_plot = WidgetDraw(this, x,x, &IFSGui::S_limit_draw);
W_limit_depth_title = WidgetText(this, "Depth: ", -1, 20);
W_limit_depth_leftarrow = WidgetLeftArrow(this, 20,20, &IFSGui::S_limit_decrease_depth);
T.str(""); T << limit_depth;
W_limit_depth_label = WidgetText(this, T.str(), -1, 20);
W_limit_depth_rightarrow = WidgetRightArrow(this, 20,20, &IFSGui::S_limit_increase_depth);
W_limit_depth_auto = WidgetCheck(this, "Auto depth", -1, 20, limit_auto_depth, &IFSGui::S_limit_auto_depth);
W_limit_chunky = WidgetCheck(this, "Chunky", -1, 20, limit_chunky, &IFSGui::S_limit_switch_chunky);
W_limit_colors = WidgetCheck(this, "Colors", -1, 20, limit_colors, &IFSGui::S_limit_switch_colors);
W_limit_zoom_title = WidgetText(this, "Zoom: ", -1, 20);
W_limit_zoom_in = WidgetButton(this, "in", 30, 20, &IFSGui::S_limit_zoom_in);
W_limit_zoom_out = WidgetButton(this, "out", 30, 20, &IFSGui::S_limit_zoom_out);
W_limit_center_title = WidgetText(this, "(Click to center)", -1, 20);
W_limit_uv_graph = WidgetCheck(this, "Plot uv graph", -1, 20, limit_uv_graph, &IFSGui::S_limit_uv_graph);
W_limit_uv_graph_depth_title = WidgetText(this, "Depth:", -1, 20);
W_limit_uv_graph_depth_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_limit_uv_graph_decrease_depth);
T.str(""); T << limit_uv_graph_depth;
W_limit_uv_graph_depth_label = WidgetText(this, T.str(), -1, 20);
W_limit_uv_graph_depth_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_limit_uv_graph_increase_depth);
W_limit_nifs = WidgetCheck(this, "nIFS", -1, 20, limit_nifs, &IFSGui::S_limit_nifs);
//W_limit_gifs = WidgetCheck(this, "gIFS", -1, 20, limit_gifs, &IFSGui::S_limit_gifs);
W_limit_2d = WidgetCheck(this, "2d IFS", -1, 20, limit_2d, &IFSGui::S_limit_2d);
pack_widget_upper_right(NULL, &W_limit_plot);
if (window_mode == LIMIT) {
pack_widget_upper_right(&W_limit_plot, &W_switch_to_mandelbrot);
pack_widget_upper_right(&W_limit_plot, &W_switch_to_combined);
}
pack_widget_upper_right(&W_limit_plot, &W_limit_center_title);
pack_widget_upper_right(&W_limit_plot, &W_limit_depth_title);
pack_widget_upper_right(&W_limit_depth_title, &W_limit_depth_leftarrow);
pack_widget_upper_right(&W_limit_depth_leftarrow, &W_limit_depth_label);
pack_widget_upper_right(&W_limit_depth_label, &W_limit_depth_rightarrow);
pack_widget_upper_right(&W_limit_plot, &W_limit_depth_auto);
pack_widget_upper_right(&W_limit_plot, &W_limit_zoom_title);
pack_widget_upper_right(&W_limit_zoom_title, &W_limit_zoom_in);
pack_widget_upper_right(&W_limit_zoom_in, &W_limit_zoom_out);
pack_widget_upper_right(&W_limit_plot, &W_limit_chunky);
pack_widget_upper_right(&W_limit_plot, &W_limit_colors);
pack_widget_upper_right(&W_limit_plot, &W_limit_uv_graph);
pack_widget_upper_right(&W_limit_plot, &W_limit_uv_graph_depth_title);
pack_widget_upper_right(&W_limit_uv_graph_depth_title, &W_limit_uv_graph_depth_leftarrow);
pack_widget_upper_right(&W_limit_uv_graph_depth_leftarrow, &W_limit_uv_graph_depth_label);
pack_widget_upper_right(&W_limit_uv_graph_depth_label, &W_limit_uv_graph_depth_rightarrow);
pack_widget_upper_right(&W_limit_plot, &W_limit_nifs);
//pack_widget_upper_right(&W_limit_plot, &W_limit_gifs);
pack_widget_upper_right(&W_limit_plot, &W_limit_2d);
}
//if the mandelbrot set is shown:
if (window_mode != LIMIT) {
W_mand_plot = WidgetDraw(this, x,x, &IFSGui::S_mand_draw);
W_mand_options_title = WidgetText(this, "mandelbrot options:", -1, 20);
W_mand_recenter = WidgetButton(this, "Recenter", -1, 20, &IFSGui::S_mand_recenter);
W_mand_zoom_title = WidgetText(this, "Zoom: ", -1, 20);
W_mand_zoom_in = WidgetButton(this, "in", -1, 20, &IFSGui::S_mand_zoom_in);
W_mand_zoom_out = WidgetButton(this, "out", -1, 20, &IFSGui::S_mand_zoom_out);
W_mand_mesh_title = WidgetText(this, "Mesh size:", -1, 20);
W_mand_mesh_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_decrease_mesh);
std::stringstream T; T.str(""); T << mand_pixel_group_size;
W_mand_mesh_label = WidgetText(this, T.str(), -1, 20);
W_mand_mesh_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_increase_mesh);
W_mand_connected_check = WidgetCheck(this, "Connectedness:", 105, 20, (mand_connected ? 1 : 0), &IFSGui::S_mand_connected);
W_mand_connected_depth_leftarrow = WidgetLeftArrow(this, 20,20, &IFSGui::S_mand_connected_decrease_depth);
T.str(""); T << mand_connected_depth;
W_mand_connected_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_connected_depth_rightarrow = WidgetRightArrow(this, 20,20, &IFSGui::S_mand_connected_increase_depth);
W_mand_contains_half_check = WidgetCheck(this, "Contains 1/2:", 105, 20, (mand_contains_half ? 1 : 0), &IFSGui::S_mand_contains_half);
W_mand_contains_half_depth_leftarrow = WidgetLeftArrow(this, 20,20, &IFSGui::S_mand_contains_half_decrease_depth);
T.str(""); T << mand_contains_half_depth;
W_mand_contains_half_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_contains_half_depth_rightarrow = WidgetRightArrow(this, 20,20, &IFSGui::S_mand_contains_half_increase_depth);
W_mand_trap_check = WidgetCheck(this, "Traps:", 105, 20, (mand_trap ? 1 : 0), &IFSGui::S_mand_trap);
W_mand_trap_depth_leftarrow = WidgetLeftArrow(this, 20,20, &IFSGui::S_mand_trap_decrease_depth);
T.str(""); T << mand_trap_depth;
W_mand_trap_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_trap_depth_rightarrow = WidgetRightArrow(this, 20,20, &IFSGui::S_mand_trap_increase_depth);
W_mand_limit_trap_check = WidgetCheck(this, "Limit traps", 105, 20, (mand_limit_trap ? 1 : 0), &IFSGui::S_mand_limit_trap);
W_mand_dirichlet_check = WidgetCheck(this, "Dirichlet:", 105, 20, mand_dirichlet, &IFSGui::S_mand_dirichlet);
W_mand_dirichlet_depth_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_dirichlet_decrease_depth);
T.str(""); T << mand_dirichlet_depth;
W_mand_dirichlet_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_dirichlet_depth_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_dirichlet_increase_depth);
W_mand_set_C_check = WidgetCheck(this, "Set C:", 105, 20, mand_set_C, &IFSGui::S_mand_set_C);
W_mand_set_C_depth_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_set_C_decrease_depth);
T.str(""); T << mand_set_C_depth;
W_mand_set_C_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_set_C_depth_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_set_C_increase_depth);
W_mand_theta_check = WidgetCheck(this, "Theta:", 105, 20, mand_set_C, &IFSGui::S_mand_theta);
W_mand_theta_depth_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_theta_decrease_depth);
T.str(""); T << mand_theta_depth;
W_mand_theta_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_theta_depth_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_theta_increase_depth);
W_mand_mouse_label = WidgetText(this, "Mouse:", 50, 20);
W_mand_mouse_X = WidgetText(this, "Re: initializing", 200, 20);
W_mand_mouse_Y = WidgetText(this, "Im: initializing", 200, 20);
W_mand_output_window = WidgetButton(this, "Write window coords", -1, 20, &IFSGui::S_mand_output_window);
W_mand_output_picture = WidgetButton(this, "Write picture", -1, 20, &IFSGui::S_mand_output_picture);
W_mand_output_picture_size_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_output_picture_decrease_size);
T.str(""); T << mand_output_picture_size;
W_mand_output_picture_size_label = WidgetText(this, T.str(), -1, 20);
W_mand_output_picture_size_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_output_picture_increase_size);
W_mand_path_create_by_drawing_button = WidgetButton(this, "Draw path", -1, 20, &IFSGui::S_mand_path_create_by_drawing_button);
W_mand_path_create_by_boundary_button = WidgetButton(this, "Find boundary path", -1, 20, &IFSGui::S_mand_path_create_by_boundary);
W_mand_path_drawing_title = WidgetText(this, "(Click to draw path)", -1, 20);
W_mand_path_finish_cancel_button = WidgetButton(this, "Cancel path", -1, 20, &IFSGui::S_mand_path_finish_cancel);
W_mand_path_finish_path_button = WidgetButton(this, "Finish path", -1, 20, &IFSGui::S_mand_path_finish_path);
W_mand_path_finish_loop_button = WidgetButton(this, "Finish loop", -1, 20, &IFSGui::S_mand_path_finish_loop);
W_mand_path_tasks_title = WidgetText(this, "Path options:", -1, 20);
W_mand_path_delete_button = WidgetButton(this, "Delete path", -2, 20, &IFSGui::S_mand_path_delete);
W_mand_path_find_traps_button = WidgetButton(this, "Find traps along path", -1, 20, &IFSGui::S_mand_path_find_traps);
W_mand_path_find_coordinates_button = WidgetButton(this, "Find coords along path", -1, 20, &IFSGui::S_mand_path_find_coordinates);
W_mand_path_create_movie_button = WidgetButton(this, "Create movie along path", -1, 20, &IFSGui::S_mand_path_create_movie);
W_mand_path_movie_length_title = WidgetText(this, "Movie length: ", -1, 20);
W_mand_path_movie_decrease_length = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_path_movie_decrease_length);
T.str(""); T << path.movie_length;
W_mand_path_movie_length_label = WidgetText(this, T.str(), -1, 20);
W_mand_path_movie_increase_length = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_path_movie_increase_length);
W_mand_path_movie_with_mandelbrot = WidgetCheck(this, "Movie with mandelbrot", -1, 20, path.movie_with_mandelbrot, &IFSGui::S_mand_path_movie_with_mandelbrot);
W_mand_path_find_uv_words_button = WidgetButton(this, "Find uv words along path", -1, 20, &IFSGui::S_mand_path_find_uv_words);
W_mand_path_find_half_words_button = WidgetButton(this, "Find half words along path", -1, 20, &IFSGui::S_mand_path_find_half_words);
W_mand_path_half_depth_title = WidgetText(this, "Half ball depth", -1, 20);
W_mand_path_half_depth_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_path_half_decrease_depth);
T.str(""); T << path.half_depth;
W_mand_path_half_depth_label = WidgetText(this, T.str(), -1, 20);
W_mand_path_half_depth_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_path_half_increase_depth);
W_mand_path_half_start_stop_title = WidgetText(this, "Start/stop:", -1, 20);
W_mand_path_half_start_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_path_half_decrease_start);
T.str(""); T << path.half_start;
W_mand_path_half_start_label = WidgetText(this, T.str(), -1, 20);
W_mand_path_half_start_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_path_half_increase_start);
W_mand_path_half_end_leftarrow = WidgetLeftArrow(this, 20, 20, &IFSGui::S_mand_path_half_decrease_end);
T.str(""); T << path.half_end;
W_mand_path_half_end_label = WidgetText(this, T.str(), -1, 20);
W_mand_path_half_end_rightarrow = WidgetRightArrow(this, 20, 20, &IFSGui::S_mand_path_half_increase_end);
if (window_mode == MANDELBROT) {
pack_widget_upper_right(NULL, &W_mand_plot);
pack_widget_upper_right(&W_mand_plot, &W_switch_to_limit);
pack_widget_upper_right(&W_mand_plot, &W_switch_to_combined);
} else {
pack_widget_upper_right(&W_limit_center_title, &W_mand_plot);
pack_widget_upper_right(&W_mand_plot, &W_switch_to_limit);
pack_widget_upper_right(&W_mand_plot, &W_switch_to_mandelbrot);
}
pack_widget_upper_right(&W_mand_plot, &W_mand_options_title);
pack_widget_upper_right(&W_mand_plot, &W_mand_recenter);
pack_widget_upper_right(&W_mand_plot, &W_mand_zoom_title);
pack_widget_upper_right(&W_mand_zoom_title, &W_mand_zoom_in);
pack_widget_upper_right(&W_mand_zoom_in, &W_mand_zoom_out);
pack_widget_upper_right(&W_mand_plot, &W_mand_mesh_title);
pack_widget_upper_right(&W_mand_mesh_title, &W_mand_mesh_leftarrow);
pack_widget_upper_right(&W_mand_mesh_leftarrow, &W_mand_mesh_label);
pack_widget_upper_right(&W_mand_mesh_label, &W_mand_mesh_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_connected_check);
pack_widget_upper_right(&W_mand_connected_check, &W_mand_connected_depth_leftarrow);
pack_widget_upper_right(&W_mand_connected_depth_leftarrow, &W_mand_connected_depth_label);
pack_widget_upper_right(&W_mand_connected_depth_label, &W_mand_connected_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_contains_half_check);
pack_widget_upper_right(&W_mand_contains_half_check, &W_mand_contains_half_depth_leftarrow);
pack_widget_upper_right(&W_mand_contains_half_depth_leftarrow, &W_mand_contains_half_depth_label);
pack_widget_upper_right(&W_mand_contains_half_depth_label, &W_mand_contains_half_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_trap_check);
pack_widget_upper_right(&W_mand_trap_check, &W_mand_trap_depth_leftarrow);
pack_widget_upper_right(&W_mand_trap_depth_leftarrow, &W_mand_trap_depth_label);
pack_widget_upper_right(&W_mand_trap_depth_label, &W_mand_trap_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_limit_trap_check);
pack_widget_upper_right(&W_mand_plot, &W_mand_dirichlet_check);
pack_widget_upper_right(&W_mand_dirichlet_check, &W_mand_dirichlet_depth_leftarrow);
pack_widget_upper_right(&W_mand_dirichlet_depth_leftarrow, &W_mand_dirichlet_depth_label);
pack_widget_upper_right(&W_mand_dirichlet_depth_label, &W_mand_dirichlet_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_set_C_check);
pack_widget_upper_right(&W_mand_set_C_check, &W_mand_set_C_depth_leftarrow);
pack_widget_upper_right(&W_mand_set_C_depth_leftarrow, &W_mand_set_C_depth_label);
pack_widget_upper_right(&W_mand_set_C_depth_label, &W_mand_set_C_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_theta_check);
pack_widget_upper_right(&W_mand_theta_check, &W_mand_theta_depth_leftarrow);
pack_widget_upper_right(&W_mand_theta_depth_leftarrow, &W_mand_theta_depth_label);
pack_widget_upper_right(&W_mand_theta_depth_label, &W_mand_theta_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_mouse_label);
pack_widget_upper_right(&W_mand_plot, &W_mand_mouse_X);
pack_widget_upper_right(&W_mand_plot, &W_mand_mouse_Y);
pack_widget_upper_right(&W_mand_plot, &W_mand_output_window);
pack_widget_upper_right(&W_mand_plot, &W_mand_output_picture);
pack_widget_upper_right(&W_mand_output_picture, &W_mand_output_picture_size_leftarrow);
pack_widget_upper_right(&W_mand_output_picture_size_leftarrow, &W_mand_output_picture_size_label);
pack_widget_upper_right(&W_mand_output_picture_size_label, &W_mand_output_picture_size_rightarrow);
if (currently_drawing_path) {
pack_widget_upper_right(&W_mand_plot, &W_mand_path_drawing_title);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_finish_cancel_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_finish_path_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_finish_loop_button);
} else if (path.is_valid) {
pack_widget_upper_right(&W_mand_plot, &W_mand_path_tasks_title);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_delete_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_traps_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_coordinates_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_create_movie_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_movie_length_title);
pack_widget_upper_right(&W_mand_path_movie_length_title, &W_mand_path_movie_decrease_length);
pack_widget_upper_right(&W_mand_path_movie_decrease_length, &W_mand_path_movie_length_label);
pack_widget_upper_right(&W_mand_path_movie_length_label, &W_mand_path_movie_increase_length);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_movie_with_mandelbrot);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_uv_words_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_find_half_words_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_half_depth_title);
pack_widget_upper_right(&W_mand_path_half_depth_title, &W_mand_path_half_depth_leftarrow);
pack_widget_upper_right(&W_mand_path_half_depth_leftarrow, &W_mand_path_half_depth_label);
pack_widget_upper_right(&W_mand_path_half_depth_label, &W_mand_path_half_depth_rightarrow);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_half_start_stop_title);
pack_widget_upper_right(&W_mand_path_half_start_stop_title, &W_mand_path_half_start_leftarrow);
pack_widget_upper_right(&W_mand_path_half_start_leftarrow, &W_mand_path_half_start_label);
pack_widget_upper_right(&W_mand_path_half_start_label, &W_mand_path_half_start_rightarrow);
pack_widget_upper_right(&W_mand_path_half_start_rightarrow, &W_mand_path_half_end_leftarrow);
pack_widget_upper_right(&W_mand_path_half_end_leftarrow, &W_mand_path_half_end_label);
pack_widget_upper_right(&W_mand_path_half_end_label, &W_mand_path_half_end_rightarrow);
} else {
pack_widget_upper_right(&W_mand_plot, &W_mand_path_create_by_drawing_button);
pack_widget_upper_right(&W_mand_plot, &W_mand_path_create_by_boundary_button);
}
}
//put the IFS data on the bottom
pack_widget_upper_right(NULL, &W_point_title);
pack_widget_upper_right(NULL, &W_point_point);
pack_widget_upper_right(NULL, &W_point_connected_check);
pack_widget_upper_right(&W_point_connected_check, &W_point_connected_leftarrow);
pack_widget_upper_right(&W_point_connected_leftarrow, &W_point_connected_depth_label);
pack_widget_upper_right(&W_point_connected_depth_label, &W_point_connected_rightarrow);
pack_widget_upper_right(&W_point_connected_rightarrow, &W_point_connected_status);
pack_widget_upper_right(NULL, &W_point_contains_half_check);
pack_widget_upper_right(&W_point_contains_half_check, &W_point_contains_half_leftarrow);
pack_widget_upper_right(&W_point_contains_half_leftarrow, &W_point_contains_half_depth_label);
pack_widget_upper_right(&W_point_contains_half_depth_label, &W_point_contains_half_rightarrow);
pack_widget_upper_right(&W_point_contains_half_rightarrow, &W_point_contains_half_status);
pack_widget_upper_right(NULL, &W_point_uv_words_check);
pack_widget_upper_right(&W_point_uv_words_check, &W_point_uv_words_leftarrow);
pack_widget_upper_right(&W_point_uv_words_leftarrow, &W_point_uv_words_depth_label);
pack_widget_upper_right(&W_point_uv_words_depth_label, &W_point_uv_words_rightarrow);
pack_widget_upper_right(&W_point_uv_words_rightarrow, &W_point_uv_words_status);
pack_widget_upper_right(NULL, &W_point_trap_check);
pack_widget_upper_right(&W_point_trap_check, &W_point_trap_leftarrow);
pack_widget_upper_right(&W_point_trap_leftarrow, &W_point_trap_depth_label);
pack_widget_upper_right(&W_point_trap_depth_label, &W_point_trap_rightarrow);
pack_widget_upper_right(&W_point_trap_rightarrow, &W_point_trap_status);
pack_widget_upper_right(NULL, &W_point_coordinates_check);
pack_widget_upper_right(&W_point_coordinates_check, &W_point_coordinates_leftarrow);
pack_widget_upper_right(&W_point_coordinates_leftarrow, &W_point_coordinates_depth_label);
pack_widget_upper_right(&W_point_coordinates_depth_label, &W_point_coordinates_rightarrow);
pack_widget_upper_right(&W_point_coordinates_rightarrow, &W_point_coordinates_status);
//invalidate the grids and stuff
if (window_mode != LIMIT) {
mand_reset_mesh();
}
//draw all the widgets
for (int i=0; i<(int)widgets.size(); ++i) {
widgets[i]->initial_draw();
}
//plot the limit set
if (window_mode != MANDELBROT) draw_limit();
if (window_mode != LIMIT) draw_mand();
//get the point data
recompute_point_data();
}
void IFSGui::main_loop() {
XEvent e;
while (true) {
XNextEvent(display, &e);
//if it was the keyboard, we deal with it here
if (e.type == KeyPress) {
if(XLookupKeysym(&e.xkey, 0) == XK_q){
break;
}
//if it involves the mouse, we find the appropriate
//widget to send it off to
} else if (e.type == ButtonPress || e.type == MotionNotify) {
for (int i=0; i<(int)widgets.size(); ++i) {
if (widgets[i]->contains_pixel( e.xbutton.x, e.xbutton.y) &&
widgets[i]->click_signal != NULL) {
(this->*(widgets[i]->click_signal))(&e);
break;
}
}
} else if (e.type == Expose) {
Point2d<int> expose_ul( e.xexpose.x, e.xexpose.y );
int ewidth = e.xexpose.width;
int eheight = e.xexpose.height;
for (int i=0; i<(int)widgets.size(); ++i) {
if (widgets[i]->intersects_rectangle(expose_ul, ewidth, eheight)) {
widgets[i]->redraw();
}
}
}
}
}
void IFSGui::launch(IFSWindowMode m, const cpx& c) {
//set the initial window mode
window_mode = m;
//set the ifs
IFS.set_params(c,c);
//set the initial settings for limit and mandelbrot
limit_ll = cpx(-1, -1.5);
limit_ur = cpx(2, 1.5);
limit_depth = 12;
limit_auto_depth = false;
limit_chunky = true;
limit_colors = true;
limit_uv_graph = false;
limit_uv_graph_depth = 3;
limit_nifs = false;
limit_gifs = false;
limit_2d = false;
limit_marked_points.resize(3);
limit_marked_points[0] = cpx(0,0);
limit_marked_points[1] = cpx(0.5,0);
limit_marked_points[2] = cpx(1.0,0);
mand_ll = cpx(-1,-1);
mand_ur = cpx(1,1);
mand_pixel_group_size = 4;
mand_connected = true;
mand_connected_depth = 13;
mand_contains_half = false;
mand_contains_half_depth = 16;
mand_trap = false;
mand_trap_depth = 20;
mand_limit_trap = false;
mand_dirichlet = false;
mand_dirichlet_depth = 3;
mand_set_C = false;
mand_set_C_depth = 10;
mand_theta = false;
mand_theta_depth = 8;
mand_output_picture_size = 1000;
point_connected_check = true;
point_connected_depth = 18;
point_is_connected = false;
point_contains_half_check = false;
point_contains_half_depth = 18;
point_is_contains_half = false;
point_uv_words_check = false;
point_uv_words_depth = 18;
point_uv_words.resize(0);
point_trap_check = false;
point_trap_depth = 12;
point_trap_words.resize(0);
point_coordinates_check = false;
point_coordinates_depth = 12;
currently_drawing_path = false;
//set up the graphics
display = XOpenDisplay(NULL);
screen = DefaultScreen(display);
if (display == NULL) {
std::cout << "Failed to open display\n";
return;
}
main_window_initialized = false;
//reset (set) the window
limit_sidebar_size = 130;
mand_sidebar_size = 170;
reset_and_pack_window();
//go for it
main_loop();
//clean up at the end
XCloseDisplay(display);
}