ranjit@eniac.seas.upenn.edu (Ranjit Bhatnagar) (08/30/88)
OK, here's a little program that can make very pretty pictures. It's primitive, but it works. I figure 90% of you missed this when it appeared in Scientific American, and another 9% didn't feel like programming it yourself - well, there you go. I recommend a magnification of 10 to start with. If you want the binary (11K before UUENCODing), send mail. If lots of people ask, I'll post it. You'll have to cut this manually, since I don't know how to SHAR things. There might be extraneous junk in the .h file, since I use the same .h (compiled) for lots of different programs. Compile with Manx 3.4b or better, link with the math library before the c library. I've never tried this except with 32 bits, large model. === CUT HERE for hop.c === /* First Wave program Ranjit Bhatnagar ranjit@eniac.seas.upenn.edu All this code is public domain - as if anyone would want to steal it. I would love to see improved versions - a nicer interface, a fixed-point implementation for speed. 30 Aug '88 Shell of First Wave has been modified to be a quick Hopalong - as described in Dewdney's Mathematical Games column, "Scientific American" Sept 86 - and invented by Barry Martin. Basically, it's an iterated function: x = 0 y = 0 for i = 1 to num plot (x, y) xx = y - sign(x)*sqrt[abs(b*x-c)] yy = a - x x = xx y = yy where a, b, and c are constants entered by the user. (Some suggested values: -1000, .1, -10; -200, .1, -80; .4, 1, 0; -3.14, .3, .3) A simpler function (not implemented here) is x = y - sin(x) y = a - x Martin recommends values of a within .07 of pi for this one. user must also specify the range of values that will be visible on the screen. [INSTEAD I put in "magnification"] Things to do: allow specification of visible range. Clever colors. Fixed-point for speed. the latest: changed to interlace, doubled pixel height, reduced frequency of checks for close-box... */ /* create a nice screen */ /* Thanks Rob Peck and "Programmer's Guide" */ struct TextAttr waveScrFont = { /* for basic methods in Intuition */ "topaz.font", 8, 0, 0 }; #define WID 640 #define HEI 400 struct NewScreen waveScr = { 0, 0, /* left and top edges */ WID, HEI, /* width and height */ 4, /* bitplanes */ 1, 0, /* detail and block pens */ LACE|HIRES, /* screen view type */ CUSTOMSCREEN, /* type */ &waveScrFont, /* font */ "Hopalong", /* title */ NULL, /* user gadgets */ NULL /* custom bitmap */ }; /* some pretty colors for it */ UWORD waveCols[] = { 0x0000, 0x0e30, 0x0fff, 0x0b40, 0x0b04, 0x05d0, 0x0ed0, 0x07df, 0x069f, 0x0c0e, 0x0f2e, 0x0feb, 0x0c96, 0x0bbb, 0x07df, 0x0bf0 }; /* and a nice window */ struct NewWindow waveWin = { 0, 15, /* left and top edges */ WID-1, HEI-16, /* size */ 2, 3, /* detail and block pens */ CLOSEWINDOW, /* flags */ SIMPLE_REFRESH | WINDOWCLOSE | GIMMEZEROZERO, NULL, NULL, "Hopalong", NULL, /* the screen */ NULL, /* the bitmap */ 10, 10, -1, -1, CUSTOMSCREEN }; /* the precomputed tables */ /* uncomment these if you decide to put fixedpoint into the program... */ /* extern WORD sinetab[];*/ /* 257 sines from 0 to 2pi, all 16 bits are frac */ /* extern WORD sqrttab[];*/ /* 257 sqrts from 0 to 256, low 12 bits are frac */ /* extern double ran(); */ /* globals */ struct Screen *scr = 0; struct Window *win = 0; struct RastPort *rp = 0; struct ViewPort *vp = 0; int GfxBase = 0; int IntuitionBase = 0; /* Open libraries & such */ OpenThings() { GfxBase = OpenLibrary("graphics.library",0); if (GfxBase == 0) Die("Couldn't open graphics.library"); diag("opened grafix"); IntuitionBase = OpenLibrary("intuition.library",0); if (IntuitionBase == 0) Die("Couldn't open intuition.library"); diag("opened intuition"); scr = OpenScreen(&waveScr); if (scr == 0) Die("Screen nailed shut"); diag("opened screen"); vp = &(scr->ViewPort); waveWin.Screen = scr; win = OpenWindow(&waveWin); if (win == 0) Die("Window painted shut"); diag("opened window"); rp = win->RPort; } /* Fail */ Die(s) char *s; { printf("%s\nSo much for this program.\n",s); CloseThings(); } /* Close libraries & such */ CloseThings() { diag("Closing everything up."); if (win) CloseWindow(win); if (scr) CloseScreen(scr); if (IntuitionBase) CloseLibrary(IntuitionBase); if (GfxBase) CloseLibrary(GfxBase); } /* display a message */ diag(s) char *s; { printf("%s\n",s); } /* THIS IS IT */ main() { struct IntuiMessage *msg; int i, j; /* current pt */ int m,n; /* just keep track of how many pixels we've plotted */ float a, b, c, x, y, xx, yy; int foo; /* sure wish C had a "sign" function and an "abs" */ float bar; float mag; OpenThings(); LoadRGB4(vp, waveCols, 16); SetDrMd(rp, JAM1); n = x = y = 0; WBenchToFront(); printf("Please enter values for a, b, c, and magnification: "); scanf("%e %e %e %e",&a,&b,&c,&mag); c = sin((double)b); /* force math library to be loaded now */ WBenchToBack(); while (0 == (msg = (struct IntuiMessage *)GetMsg(win->UserPort))) { for (m=0; m<100; m++) { /* check for messages only every 100th */ SetAPen(rp, (++n >> 8) % 16);/* for now, color changes every 256 pts */ i = (int)(WID/2+mag*x) % 2000; /* 2000 picked out of a hat */ j = (int)(HEI/2+mag*y) % 2000; WritePixel(rp, i, j); WritePixel(rp, i, j+1); /* why? To reduce interlace flicker */ if (x<0) foo=-1; else foo=1; if ((bar=b*x-c)<0) bar=-bar; xx = y - foo*sqrt((double)bar); yy = a - x; x = xx; y = yy; } } do { ReplyMsg(msg); } while (msg = (struct IntuiMessage *)GetMsg(win->UserPort)); finish: CloseThings(); } === CUT HERE for hop.h === /* Include file for First Wave Program - started 10 Dec 87 Appropriated for Hopalong, the program that will put me in the Hall of Fame - 30 Aug 88 */ #include <exec/types.h> #include <intuition/intuition.h> #include <graphics/gfxmacros.h> #include <math.h> === CUT HERE for .signature and apology (not necessarily in that order) === This is not a very long posting, but if you think it's too long, sorry! === === === Pa! Molly's dead! She ate some leaves! === === === "Trespassers w" ranjit@eniac.seas.upenn.edu ucbvax!rutgers!super!eniac!... Ranjit Bhatnagar, Graduate Student I'm not an actor, but I play one on TV.