french@caip.RUTGERS.EDU (12/27/85)
From: "french robert%d.mfenet"@LLL-MFE.ARPA /* MAND1.C - Graphics routines Mandelbrot Self-Squared Dragon Generator For the Commodore Amiga Version 1.00 Accompanies MAND.C Copyright (c) 1985, Robert S. French Placed in the Public Domain This program may be distributed free of charge as long as the above notice is retained. */ /*-------------------*/ /* Lots of includes! */ #include <exec/types.h> #include <exec/tasks.h> #include <exec/libraries.h> #include <exec/devices.h> #include <devices/keymap.h> #include <graphics/copper.h> #include <graphics/display.h> #include <graphics/gfxbase.h> #include <graphics/text.h> #include <graphics/view.h> #include <graphics/gels.h> #include <graphics/regions.h> #include <hardware/blit.h> #include <intuition/intuition.h> #include <intuition/intuitionbase.h> #include <stdio.h> /*-------------------*/ /* Misc. definitions */ #define EVER ;; #define MAXX 640 #define MAXY 390 #define STARTY 10 #define TOPW2 w2->BorderTop #define BOTTOMW2 (w2->Height - w2->BorderBottom) #define LEFTW2 w2->BorderLeft #define RIGHTW2 (w2->Width - w2->BorderRight) /*---------------------------------*/ /* Fast-Floating-Point Definitions */ extern int SPFix(); extern int SPFlt(); extern int SPCmp(); extern int SPTst(); extern int SPAbs(); extern int SPNeg(); extern int SPAdd(); extern int SPSub(); extern int SPMul(); extern int SPDiv(); extern int SPAtan(); extern int SPSin(); extern int SPCos(); extern int SPTan(); extern int SPSincos(); extern int SPSinh(); extern int SPCosh(); extern int SPTanh(); extern int SPExp(); extern int SPLog(); extern int SPPow(); extern int SPSqrt(); extern int SPTieee(); extern int SPFieee(); extern int MathBase,MathTransBase; /*----------------------*/ /* Graphics definitions */ extern struct GfxBase *GfxBase; extern struct IntuitionBase *IntuitionBase; struct RastPort *rp,*rp2; struct ViewPort *vp; struct TextAttr TextFont = { "topaz.font", /* Standard system font */ 8, 0, 0 }; struct Window *w,*w2; struct Screen *screen; struct IntuiMessage *message; struct NewScreen ns = { 0, 0, /* start position */ 320, 200, 6, /* width, height, depth */ 0, 1, /* detail pen, block pen */ HAM, /* Hold and Modify ViewMode */ CUSTOMSCREEN, /* screen type */ &TextFont, /* font to use */ "", /* default title for screen */ NULL /* pointer to additional gadgets */ }; struct NewWindow nw = { 0, 0, /* start position */ 320, 200, /* width, height */ -1, -1, /* detail pen, block pen */ CLOSEWINDOW|MOUSEBUTTONS, /* IDCMP flags */ ACTIVATE|WINDOWCLOSE|BORDERLESS|BACKDROP, /* window flags */ NULL, /* pointer to first user gadget */ NULL, /* pointer to user checkmark */ "Mandelbrot Dragons", /* window title */ NULL, /* pointer to screen (set below) */ NULL, /* pointer to superbitmap */ 0, 0, 320, 200, /* ignored since not sizeable */ CUSTOMSCREEN /* type of screen desired */ }; struct NewWindow aw = { 0, 10, 100, 70, -1, -1, NULL, WINDOWDRAG|WINDOWSIZING|SMART_REFRESH, NULL, NULL, "Analysis", NULL, NULL, 0, 0, 320, 200, CUSTOMSCREEN }; long last_color; /*----------------------------------*/ /* Miscellaneous Global Definitions */ extern union kludge { float f; int i; } start_r,end_r,start_i,end_i; /* Block bounds for set */ extern int max_x,max_y; /* Graphics window size */ extern int max_count,color_inc,color_offset,color_set,color_mode,color_div; extern int color_inset,func_num; extern int v_starty,max_mem; extern long v_offset; extern UWORD *color_table,*v_mand_store; extern int modified,want_read; extern FILE *console,*v_fp,*redir_fp; /*----------------*/ /* Color routines */ init_colors() { switch (color_set) { case 0: init_cincr(); break; case 1: init_c7rot(); break; } } init_cincr() { UWORD i; for (i=0;i<4096;i++) *(color_table + i) = i; } init_c7rot() { UWORD i,j,*base; base = color_table; *(base++) = 0; for (j=0;j<39;j++) { for (i=1;i<16;i++) *(base++) = i; for (i=1;i<16;i++) *(base++) = i << 4; for (i=1;i<16;i++) *(base++) = i << 8; for (i=1;i<16;i++) *(base++) = i | (i << 4); for (i=1;i<16;i++) *(base++) = i | (i << 8); for (i=1;i<16;i++) *(base++) = (i << 4) | (i << 8); for (i=1;i<16;i++) *(base++) = i | (i << 4) | (i << 8); } } /*----------------*/ /* Other routines */ open_winds() { int i,color; nw.Width = max_x; nw.Height = max_y+STARTY; if (color_mode & 1) { ns.ViewModes = NULL; ns.Depth = 5; } else { ns.ViewModes = HAM; ns.Depth = 6; } if (color_mode & 2) { ns.ViewModes |= INTERLACE; ns.Height = 400; } else ns.Height = 200; if (color_mode & 4) { ns.Width = 640; ns.ViewModes |= HIRES; ns.Depth = 4; } else ns.Width = 320; screen = (struct Screen *)OpenScreen(&ns); if (screen == NULL) { fputs("Can't open new screen!\n",console); return (1); } ShowTitle(screen,FALSE); nw.Screen = screen; w = (struct Window *)OpenWindow(&nw); if (w == NULL) { CloseScreen(screen); fputs("Can't open new window!\n",console); return (1); } vp = &screen->ViewPort; rp = w->RPort; SetDrMd(rp,JAM1); SetBPen(rp, 0); if (color_mode & 1) for (i=0;i<28;i++) { color = *(color_table+i*color_inc); SetRGB4(vp,i+4,(color >> 8) & 0xf,(color >> 4) & 0xf,color & 0xf); } return (0); } void wait_close() { ULONG class; USHORT code; if (redir_fp) { Delay(600); CloseWindow(w); CloseScreen(screen); return; } for (EVER) { if (message = (struct IntuiMessage *)GetMsg(w->UserPort)) { class = message->Class; code = message->Code; ReplyMsg(message); if (class == CLOSEWINDOW) { CloseWindow(w); CloseScreen(screen); return; } } } } gen_mand() { void write_out(); int x_coord,y_coord,count; union kludge x_gap,y_gap,z_r,z_i,u_r,u_i,temp,temp2,temp3,const0; union kludge const1,const2,const12; ULONG class; USHORT code; if (v_fp) { fclose(v_fp); v_fp = NULL; } v_fp = fopen("Mandelbrot.temp.file","w+"); if (v_fp == NULL) { abort("Can't open temporary file!"); } v_starty = 1; v_offset = 0L; modified = FALSE; want_read = FALSE; if (open_winds()) return (1); x_gap.i = SPDiv(SPFlt(max_x),SPSub(start_r.i,end_r.i)); y_gap.i = SPDiv(SPFlt(max_y),SPSub(start_i.i,end_i.i)); const0.i = SPFlt(0); const1.i = SPFlt(1); const2.i = SPFlt(2); const12.i = SPDiv(SPFlt(2),SPFlt(1)); for (y_coord=0;y_coord<max_y;y_coord++) { last_color = 0xfff; v_pos_line(y_coord); modified = TRUE; for (x_coord=0;x_coord<max_x;x_coord++) { while (message = (struct IntuiMessage *)GetMsg(w->UserPort)) { class = message->Class; code = message->Code; ReplyMsg(message); /* This routine crashes for some reason, thus it is left out if (class == CLOSEWINDOW) { CloseWindow(w); CloseScreen(screen); fclose(v_fp); v_fp = NULL; return (0); } */ } if (func_num == 0) z_r.i = const0.i; else z_r.i = const12.i; z_i.i = const0.i; u_r.i = SPAdd(start_r.i,SPMul(SPFlt(x_coord),x_gap.i)); u_i.i = SPAdd(start_i.i,SPMul(SPFlt(max_y-y_coord-1),y_gap.i)); count = 0; for (count=0;SPFix(SPAdd(SPMul(z_r.i,z_r.i),SPMul(z_i.i,z_i.i)))<4&&(count<max_count);count++) { if (func_num == 0) { /* z = z^2-u */ temp.i = SPSub(u_r.i,SPSub(SPMul(z_i.i,z_i.i),SPMul(z_r.i,z_r.i))); z_i.i = SPSub(u_i.i,SPMul(SPMul(const2.i,z_r.i),z_i.i)); z_r = temp; } else if (func_num == 1) { /* z = uz(1-z) */ temp2.i = SPSub(z_r.i,const1.i); temp3.i = SPNeg(z_i.i); temp.i = SPSub(SPMul(temp3.i,z_i.i),SPMul(temp2.i,z_r.i)); z_i.i = SPAdd(SPMul(temp2.i,z_i.i),SPMul(temp3.i,z_r.i)); z_r = temp; temp.i = SPSub(SPMul(z_i.i,u_i.i),SPMul(z_r.i,u_r.i)); z_i.i = SPAdd(SPMul(z_r.i,u_i.i),SPMul(z_i.i,u_r.i)); z_r = temp; } } if (count >= max_count) count = 0; *(v_mand_store+(y_coord-v_starty)*max_x+x_coord) = count; write_out(count,x_coord,y_coord); } } return (0); } disp_mand() { void write_out(); int x_coord,y_coord,count; if (open_winds()) return (1); want_read = TRUE; for (y_coord=0;y_coord<max_y;y_coord++) { last_color = 0xfff; v_pos_line(y_coord); for (x_coord=0;x_coord<max_x;x_coord++) { count = *(v_mand_store+(y_coord-v_starty)*max_x+x_coord); write_out(count,x_coord,y_coord); } } return (0); } anal_mand() { union kludge x_gap,y_gap,z_r,z_i,u_r,u_i,const0,const1,const2,const4; union kludge const12,temp,temp2,temp3; int count,x,y,width,height,last_x,last_y,select,lines; ULONG class; USHORT code; if (disp_mand()) return (1); x_gap.i = SPDiv(SPFlt(max_x),SPSub(start_r.i,end_r.i)); y_gap.i = SPDiv(SPFlt(max_y),SPSub(start_i.i,end_i.i)); const0.i = SPFlt(0); const1.i = SPFlt(1); const2.i = SPFlt(2); const4.i = SPFlt(4); const12.i = SPDiv(SPFlt(2),SPFlt(1)); last_x = -1; last_y = -1; select = 0; lines = 0; aw.Screen = screen; w2 = (struct Window *)OpenWindow(&aw); if (w2 == NULL) { CloseWindow(w); CloseScreen(screen); fputs("Can't open analyzing window\n",console); return (1); } rp2 = w2->RPort; SetDrMd(rp2,JAM1); SetBPen(rp2, 0); SetAPen(rp2, 1); RectFill(rp2,LEFTW2+1,TOPW2+1,RIGHTW2-1,BOTTOMW2-1); for (EVER) { if (message = (struct IntuiMessage *)GetMsg(w->UserPort)) { class = message->Class; code = message->Code; ReplyMsg(message); if (class == CLOSEWINDOW) { CloseWindow(w2); CloseWindow(w); CloseScreen(screen); return (0); } if (class == MOUSEBUTTONS) if (code == SELECTDOWN) { if (w->MouseY < STARTY) lines = !lines; else select = TRUE; } else if (code == SELECTUP) select = FALSE; } if ((last_x != w->MouseX || last_y != w->MouseY) && select && w->MouseX < max_x && w->MouseY >= STARTY && w->MouseY < max_y+STARTY) { last_x = w-> MouseX; last_y = w-> MouseY; SetAPen(rp2,1); RectFill(rp2,LEFTW2+1,TOPW2+1,RIGHTW2-1,BOTTOMW2-1); width = RIGHTW2 - LEFTW2 - 6; height = BOTTOMW2 - TOPW2 - 4; SetAPen(rp2,3); Move(rp2,LEFTW2+2,TOPW2+height/2+2); Draw(rp2,RIGHTW2-2,TOPW2+height/2+2); Move(rp2,LEFTW2+width/2+3,TOPW2+2); Draw(rp2,LEFTW2+width/2+3,BOTTOMW2-2); SetAPen(rp2,2); if (func_num == 0) z_r.i = const0.i; else z_r.i = const12.i; z_i.i = const0.i; u_r.i = SPAdd(start_r.i,SPMul(SPFlt(last_x),x_gap.i)); u_i.i = SPAdd(start_i.i,SPMul(SPFlt(max_y-(last_y-STARTY)-1),y_gap.i)); count = 0; for (count=0;SPFix(SPAdd(SPMul(z_r.i,z_r.i),SPMul(z_i.i,z_i.i)))<4&&(count<max_count);count++) { temp.i = SPDiv(const4.i,SPMul(z_r.i,SPFlt(width))); x = SPFix(temp.i); temp.i = SPDiv(const4.i,SPMul(z_i.i,SPFlt(height))); y = SPFix(temp.i); if (!lines) if (x != 0 || y != 0) WritePixel(rp2,x+width/2+LEFTW2+3,height/2-y+TOPW2+2); else ; else if (count == 0) Move(rp2,x+width/2+LEFTW2+3,height/2-y+TOPW2+2); else Draw(rp2,x+width/2+LEFTW2+3,height/2-y+TOPW2+2); if (func_num == 0) { /* z = z^2-u */ temp.i = SPSub(u_r.i,SPSub(SPMul(z_i.i,z_i.i),SPMul(z_r.i,z_r.i))); z_i.i = SPSub(u_i.i,SPMul(SPMul(const2.i,z_r.i),z_i.i)); z_r = temp; } else if (func_num == 1) { /* z = uz(1-z) */ temp2.i = SPSub(z_r.i,const1.i); temp3.i = SPNeg(z_i.i); temp.i = SPSub(SPMul(temp3.i,z_i.i),SPMul(temp2.i,z_r.i)); z_i.i = SPAdd(SPMul(temp2.i,z_i.i),SPMul(temp3.i,z_r.i)); z_r = temp; temp.i = SPSub(SPMul(z_i.i,u_i.i),SPMul(z_r.i,u_r.i)); z_i.i = SPAdd(SPMul(z_r.i,u_i.i),SPMul(z_i.i,u_r.i)); z_r = temp; } } } } } void write_out(color,x,y) int color,x,y; { void ham_write(); y += STARTY; if (!(color_mode & 1)) { if (color == 0) color = color_inset; else color = color*color_inc+color_offset; ham_write(*(color_table+color),x,y); } else if ((color_mode & 1) && !(color_mode & 4)) { if (color == 0) color = color_inset % 28; else color = (((color-1)/color_div+color_offset) % 28); SetAPen(rp,color+4); WritePixel(rp,x,y); } else if (color_mode & 4) { if (color == 0) color = color_inset % 12; else color = (((color-1)/color_div+color_offset) % 12); SetAPen(rp,color+4); WritePixel(rp,x,y); } } void ham_write(color, x, y) int color; int x, y; { if ((color & 0xf00) != (last_color & 0xf00)) { SetAPen(rp,((color & 0xf00) >> 8) + 0x20); WritePixel(rp,x,y); last_color = (last_color & 0xff) | (color & 0xf00); return; } if ((color & 0xf0) != (last_color & 0xf0)) { SetAPen(rp,((color & 0xf0) >> 4) + 0x30); WritePixel(rp,x,y); last_color = (last_color & 0xf0f) | (color & 0xf0); return; } SetAPen(rp,(color & 0xf) + 0x10); WritePixel(rp,x,y); last_color = (last_color & 0xff0) | (color & 0xf); return; }