/* fractal.c draw trees */ #include #include #include #include #include #include static Display *dpy; static Window window1; static GC gc; static Screen *screen; static int screen_num; static Colormap cmap; static int status; static XColor white_c, black_c, green_c, exact_c; static int w1W = 600; static int w1H = 500; static int line_style = 0; /* LineSolid */ static int cap_style = 2; /* CapRound */ static int join_style = 1; /* JoinRound */ int linewidth = 1; float height = 80.0; float width = 20.0; float left_alpha = 2.0; float right_alpha = 2.2; float left_angle = 20.0; float right_angle = 26.0; int level_in = 14; float left_width_factor; float right_width_factor; float left_height_factor; float right_height_factor; int level; float x, y, x1, y01; float turtle_x, turtle_y, turtle_r, turtle_theta; static void generate(float x, float y, float width, float height, float angle, int level); static void turn(float angle); static float point(float x1, float y01, float x2, float y2); static void step(void); static void doInitialize(void); /* function prototypes used below */ static void doCreateWindows(void); static void doCreateGraphicsContext(void); static void doExpose(XEvent *eventP); static void doHandleEvents(void); /********************** The main program *******************************/ int main(int argc, char *argv[]) { /* may read command line */ printf("height=%g, width=%g, left_alpha=%g, right_alpha=%g,\n left_angle=%g, right_angle=%g, level_in=%d \n", height, width, left_alpha, right_alpha, left_angle, right_angle, level_in); doInitialize(); doHandleEvents(); /* this never returns */ return 0; } /***************** doInitialize **************************/ static void doInitialize(void) { dpy = XOpenDisplay(0); if (!dpy) { printf("Display not opened!\n"); exit(1); } screen = XDefaultScreenOfDisplay(dpy); screen_num = XDefaultScreen(dpy); cmap = XDefaultColormap(dpy, screen_num); status = XAllocNamedColor(dpy, cmap, "white", &white_c, &exact_c); if (!status) printf("no white \n"); status = XAllocNamedColor(dpy, cmap, "black", &black_c, &exact_c); if (!status) printf("no black \n"); status = XAllocNamedColor(dpy, cmap, "green", &green_c, &exact_c); if (!status) printf("no green \n"); doCreateWindows(); doCreateGraphicsContext(); XStoreName(dpy, window1, "fractal"); XMapWindow(dpy, window1); } /******* doCreateWindows *********/ static void doCreateWindows(void) { int window1X = 0; int window1Y = 0; XSetWindowAttributes xswa; /* Create the window1 window */ xswa.event_mask = ExposureMask | ButtonPressMask; xswa.background_pixel = XWhitePixelOfScreen(screen); window1 = XCreateWindow(dpy, XRootWindowOfScreen(screen), window1X, window1Y, w1W, w1H, 0, XDefaultDepthOfScreen(screen), InputOutput, XDefaultVisualOfScreen(screen), CWEventMask | CWBackPixel, &xswa); } /******** Create the graphics context *********/ static void doCreateGraphicsContext(void) { XGCValues xgcv; /* Create graphics context. */ xgcv.background = XWhitePixelOfScreen(screen); xgcv.foreground = XBlackPixelOfScreen(screen); gc = XCreateGC(dpy, window1, GCForeground | GCBackground, &xgcv); XSetForeground(dpy, gc, black_c.pixel); XSetLineAttributes(dpy, gc, linewidth, line_style, cap_style, join_style); } /****************** doHandleEvents ***********************/ static void doHandleEvents(void) { XEvent event; for ( ; ; ) { XNextEvent(dpy, &event); switch (event.type) { case Expose: doExpose(&event); break; case ButtonPress: exit(0); /* shut down */ } } } /***** draw in the window *****/ static void doExpose(XEvent *eventP) { /* If this is an expose event on our window1 window, then write out the fractal. */ if (eventP->xexpose.window != window1) return; XClearWindow(dpy, window1); /* continuing main from generate trees */ level = level_in; left_width_factor = pow(2, -1/left_alpha); right_width_factor = pow(2, -1/right_alpha); left_height_factor = pow(2, -2/(3*left_alpha)); right_height_factor = pow(2, -2/(3*right_alpha)); x = w1W/2.0; y = w1H/10.0; linewidth = width; XSetForeground(dpy, gc, black_c.pixel); XSetLineAttributes(dpy, gc, linewidth, line_style, cap_style, join_style); x1 = x; y01 = y+height; XDrawLine(dpy, window1, gc, (int)x, w1H-(int)y, (int)x1, w1H-(int)y01); turtle_r = height; turtle_theta = point(x, y, x1, y01); turtle_x = x; turtle_y = y; turn(left_angle); generate(x1, y01, left_width_factor*width, left_height_factor*height, left_angle, level); turtle_theta = point(x, y, x1, y01); turn(-right_angle); generate(x1, y01, left_width_factor*width, left_height_factor*height, right_angle, level); } static void generate(float x, float y, float width, float height, float angle, int level) { float x1, y01; turtle_x = x; turtle_y = y; turtle_r = height; step(); x1 = turtle_x; y01 = turtle_y; linewidth = width; XSetLineAttributes(dpy, gc, linewidth, line_style, cap_style, join_style); level--; if(level<3) { XSetForeground(dpy, gc, green_c.pixel); XDrawLine(dpy, window1, gc, (int)x, w1H-(int)y, (int)x1, w1H-(int)y01); } else { XSetForeground(dpy, gc, black_c.pixel); XDrawLine(dpy, window1, gc, (int)x, w1H-(int)y, (int)x1, w1H-(int)y01); } if(level>0) { turtle_theta = point(x, y, x1, y01); turn(left_angle); generate(turtle_x, turtle_y, left_width_factor*width, left_height_factor*height, left_angle, level); turtle_theta = point(x, y, x1, y01); turn(-right_angle); generate(x1,y01, left_width_factor*width, left_height_factor*height, right_angle, level); } } static void turn(float angle) { turtle_theta += angle; } static float point(float x1, float y01, float x2, float y2) { float theta; if((x2-x1)==0.0) { if(y2>y01) theta=90.0; else theta=270.0; } else { theta=atan((y2-y01)/(x2-x1))*57.295779; } if(x1>x2) theta += 180.0; return theta; } static void step(void) { turtle_x += turtle_r*cos(turtle_theta*0.017453292); turtle_y += turtle_r*sin(turtle_theta*0.017453292); }