home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Science
/
Science.zip
/
MANDELPM.ZIP
/
MANDELDO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-07
|
17KB
|
778 lines
/*
* Microsoft C 5.1 source code
* { Turbo Pascal 4.0 source code }
* {$I-}
* program Mandel;
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#if OS2
#define INCL_DOS
#define INCL_WIN
#define INCL_GPI
#ifdef M_I386
#define huge
#define far
#define _far
#define halloc(a,b) malloc(a*b)
#define CREATETHREAD(a,b,c,d) _beginthread(a,d,NULL)
#else
#define CREATETHREAD(a,b,c,d) (c=malloc(d),DosCreateThread(a,b,c+d))
#endif
#include "os2.h"
#include "api2.h"
static HBITMAP hbm = NULL;
static HDC hdm ;
static HPS hpm ;
HAB hab;
HPS hps;
#define plotflag 0x10000L
HWND hwndframe, hwndclient;
#define delay(x) DosSleep((ULONG)(x))
#define keypressed keypress
#define putpixel(x,y,c) (bitmap[(iymax-1-(y))*(ULONG)ixmax+(x)] = (c),\
plot((x),iymax-1-(y),(c)))
#else
#ifndef UCHAR
typedef unsigned int UCHAR;
#endif
#ifndef USHORT
typedef unsigned int USHORT;
#endif
#ifndef ULONG
typedef unsigned long ULONG;
#endif
#ifndef UINT
typedef unsigned int UINT;
#endif
#ifndef PVOID
typedef void _far * PVOID;
#endif
#include "graph.h"
#define refresh(i)
#define quit exit
#define delay dosdelay
#define keypressed kbhit
#define putpixel(x,y,c) { _setcolor(c); _setpixel((x),(y)); }
#endif
USHORT palflag = 1;
typedef void far *HANDLE;
#define CX1 320
#define CY1 200
#define MAXPAL 64
#define NCOLORS 256
#define NN (ncolors/3)
#define MAXCOLOR (NN*3)
#define random(x) ((ULONG)rand() * (x) >> 15)
#define abs(x) ((x) < 0 ? -(x) : (x))
#define SETRGB(r,g,b) (((ULONG)(r)<<16) | ((g) << 8) | (b))
USHORT ncolors = 16, key=0;
static int sem=0;
USHORT ixmax, iymax, xscreen,yscreen;
#define real double
int MAX_ITERATIES = 100;
int log=0;
#define MAXITER_MIN 50
#define MAXITER_MAX 1000
int firstcolor = 0;
#define MAX_VALUE 4.0
#define NORMAL 0
#define INIT 1
real range, delta_x, delta_y, x_coord, y_coord;
int x,y;
#define MAX_X ixmax
#define MAX_Y iymax
int arg_c; char **arg_v;
typedef union
{
ULONG mask;
struct
{
UCHAR blue;
UCHAR green;
UCHAR red;
} color;
UCHAR array[3];
} COLORS;
#define F 2 /* the "roughness" of the image */
char huge *bitmap;
char ch;
COLORS p[NCOLORS];
COLORS ctbl[NCOLORS];
/* static USHORT colorgrad[] = { 1, 2, 4, 9, 10, 11, 13 } ; */
static USHORT colorgrad[] = { 1, 2, 3, 4, 5, 6, 7 } ;
USHORT ngrad = (sizeof(colorgrad)/sizeof(USHORT));
FILE *image;
USHORT ixmax, iymax, cx, cy;
char active=0;
USHORT duration=0;
#if OS2
/* should be called from WM_CHAR message */
int charfrommsg(MPARAM mp1, MPARAM mp2)
{
int i,ctrl=0,vk; USHORT ch;
int state = 0;
ch = SHORT1FROMMP(mp2); /* char code */
vk = SHORT2FROMMP(mp2); /* virtual key code */
i = SHORT1FROMMP(mp1);
if (i & KC_KEYUP)
return 0 ;
if (i & KC_INVALIDCHAR)
return 0 ;
if (i & KC_SHIFT)
state |= 0x300;
if (i & KC_CTRL)
state |= 0x400;
if (i & KC_ALT)
state |= 0x800;
if (!vk)
{
ctrl = (i & KC_CTRL);
}
else
{
switch (vk)
{
case VK_SHIFT:
case VK_CTRL:
case VK_ALT:
return 0;
case VK_BACKSPACE:
return 8 | state;
case VK_ENTER:
case VK_NEWLINE:
return 13 | state;
case VK_ESC:
return 27 | state;
case VK_SPACE:
return ' ' | state;
case VK_TAB:
return 9 | state;
default:
return vk | 0x80 | state;
}
}
i = CHAR1FROMMP(mp2); /* ascii code */
if (i && ctrl)
{
return (i & 0x1F) | state; /* control key */
}
return i; /* | state; */
}
int keypress()
{
if (key == 27)
return key;
return 0;
}
MRESULT EXPENTRY wndproc (HWND, USHORT, MPARAM, MPARAM) ;
main(int argc, char **argv)
{
static char name [] = "mandel" ;
static ULONG fl =
FCF_SHELLPOSITION ;
HMQ hmq ;
QMSG qmsg ;
RECTL r;
arg_c = argc; arg_v = argv;
hab = WinInitialize (0) ;
hmq = WinCreateMsgQueue (hab, 0) ;
WinRegisterClass (
hab, /* Anchor block handle */
name, /* Name of class being registered */
wndproc, /* Window procedure for class */
CS_SIZEREDRAW, /* Class style */
0) ; /* Extra bytes to reserve */
cx = ixmax = CX1;
cy = iymax = CY1;
hwndframe = WinCreateStdWindow (
HWND_DESKTOP, /* Parent window handle */
0L, /* Style of frame window */
&fl, /* Pointer to control data */
name, /* Client window class name */
"Mandelbrot", /* Title bar text */
0L, /* Style of client window */
NULL, /* Module handle for resources */
0, /* ID of resources */
&hwndclient) ; /* Pointer to client window handle */
fl = SWP_SHOW;
if (argoption('b'))
fl = SWP_SHOW;
r.xLeft = 0;
r.yBottom = 0;
r.xRight = CX1;
r.yTop = CY1;
WinCalcFrameRect(hwndframe,&r,0);
/* if (argoption('f')) */
fl |= SWP_MAXIMIZE;
WinSetWindowPos(hwndframe,NULL, 60,60,r.xRight-r.xLeft, r.yTop-r.yBottom,fl);
while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
WinDispatchMsg (hab, &qmsg) ;
WinDestroyWindow (hwndframe) ;
WinDestroyMsgQueue (hmq) ;
WinTerminate (hab) ;
return 0 ;
}
makebitmap()
{
int i;
static BITMAPINFO *pbmi ;
static BITMAPINFOHEADER bmp ;
if (!hbm)
{
/*--------------------------
Create 320 by 200 bitmap
--------------------------*/
bmp.cbFix = sizeof bmp ;
bmp.cx = ixmax;
bmp.cy = iymax;
bmp.cPlanes = 1 ;
bmp.cBitCount = 8 ;
if (!pbmi)
{
pbmi = malloc (sizeof (BITMAPINFO) + sizeof (RGB)*(NCOLORS-1)) ;
memmove(pbmi, &bmp, sizeof(bmp));
for (i=0; i<ncolors; i++)
{
pbmi->argbColor[i].bRed = ctbl[i].color.red ;
pbmi->argbColor[i].bGreen = ctbl[i].color.green;
pbmi->argbColor[i].bBlue = ctbl[i].color.blue ;
}
}
hbm = GpiCreateBitmap(hps, &bmp, CBM_INIT,
bitmap, (PBITMAPINFO)pbmi);
GpiSetBitmap (hps, hbm) ;
}
return TRUE;
}
void _cdecl leave(int i)
{
sem = 3;
}
clearsquare(int x1, int y1, int x2, int y2, int color)
{
RECTL r;
if (x1 < x2 && y1 < y2)
{
r.xLeft = x1;
r.xRight = x2;
r.yTop = y2;
r.yBottom = y1;
WinFillRect(hps, &r, color == -1 ? CLR_BACKGROUND : ctbl[color].mask);
}
}
redraw(int read)
{
POINTL ptl[4];
RECTL r;
if (!sem)
GpiErase(hps);
else /* clear remainder of window */
{
clearsquare(0, iymax, cx, cy, -1);
clearsquare(ixmax, 0, cx, iymax, -1);
}
if (!sem)
return 0;
makebitmap();
r.xLeft = 0;
r.yBottom = 0;
r.xRight = ixmax;
r.yTop = iymax;
ptl[0].x = ptl[2].x = 0;
ptl[0].y = ptl[2].y = 0;
ptl[1].x = cx;
ptl[1].y = cy;
ptl[3].x = ixmax;
ptl[3].y = iymax;
if (hbm)
{
WinDrawBitmap(hps,hbm,&r,&ptl[0],0L,0L,DBM_IMAGEATTRS);
/* GpiWCBitBlt(hps, hbm, 4L, ptl, ROP_SRCCOPY, BBO_IGNORE); */
GpiDeleteBitmap(hbm);
hbm = NULL;
}
return 0 ;
}
refresh(int i)
{
WinInvalidateRect(hwndclient,NULL ,0);
WinUpdateWindow(hwndclient);
}
static int hidden;
int showhide(HANDLE h, int flag)
{
static HWND h1,h2,h3,h4;
static int start;
if (!h) h = hwndframe;
/*
Hide the title bar and associated controls
*/
if (!hidden && flag) /* no hide at end of program */
{
if (!start)
{
h1 = WinWindowFromID ( h , FID_TITLEBAR ) ;
h2 = WinWindowFromID ( h , FID_SYSMENU ) ;
h3 = WinWindowFromID ( h , FID_MINMAX ) ;
h4 = WinWindowFromID ( h , FID_MENU ) ;
start = 1;
}
hidden = 1;
if (h1) WinSetParent ( h1 , HWND_OBJECT , FALSE ) ;
if (h2) WinSetParent ( h2 , HWND_OBJECT , FALSE ) ;
if (h3) WinSetParent ( h3 , HWND_OBJECT , FALSE ) ;
if (h4) WinSetParent ( h4 , HWND_OBJECT , FALSE ) ;
WinSendMsg ( h , WM_UPDATEFRAME ,
( MPARAM ) ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX | FCF_MENU ) ,
NULL ) ;
}
else if (hidden)
/*
Show the title bar and associated controls
*/
{
hidden = 0;
if (h1) WinSetParent ( h1 , h , FALSE ) ;
if (h2) WinSetParent ( h2 , h , FALSE ) ;
if (h3) WinSetParent ( h3 , h , FALSE ) ;
if (h4) WinSetParent ( h4 , h , FALSE ) ;
WinSendMsg ( h , WM_UPDATEFRAME ,
( MPARAM ) ( FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX | FCF_MENU ) ,
NULL ) ;
if (flag)
WinInvalidateRect ( h , NULL , TRUE ) ;
}
}
int colorinit(ULONG far * xscreen, ULONG far *yscreen, USHORT far * ncolors,
COLOR far * deftbl)
{
HPS hps;
HDC hdc;
LONG l,x,y;
char far *p;
int i, c_ncolors;
hps = WinGetPS(HWND_DESKTOP);
hdc = GpiQueryDevice(hps);
DevQueryCaps(hdc,CAPS_COLORS, 1L, &x);
c_ncolors = (USHORT) x;
if (x == 0x1000000L)
c_ncolors = 24;
DevQueryCaps(hdc,CAPS_WIDTH, 1L, &x);
DevQueryCaps(hdc,CAPS_HEIGHT, 1L, &y);
if (c_ncolors != 24)
{
GpiQueryRealColors(hps,LCOLOPT_REALIZED,0L,(ULONG)c_ncolors,(COLOR*)deftbl);
}
*ncolors = c_ncolors;
*xscreen = x;
*yscreen = y;
WinReleasePS(hps);
return TRUE;
}
initcolors()
{
HDC hdc;
ULONG x,y;
SIZEL SL;
hdc = WinOpenWindowDC(hwndclient);
colorinit(&x, &y, &ncolors, (PVOID)ctbl);
ixmax = x;
iymax = y;
xscreen = x;
yscreen = y;
SL.cx = 0000;
SL.cy = 0000;
hps = GpiCreatePS(hab,hdc,&SL,PU_PELS | GPIF_DEFAULT | GPIT_NORMAL |
GPIA_ASSOC);
GpiCreateLogColorTable(hps,LCOL_RESET,LCOLF_RGB,0L,0L,0L);
}
void far thread()
{
int i,j;
WinInitialize(0);
if (!bitmap)
bitmap = halloc(((ULONG)ixmax*iymax) >> 4, 0x10);
if (!bitmap)
exit(1);
for (i=0; i<ixmax; i++) /* initialize with zeroes */
{
for (j=0; j<iymax; j++)
bitmap[(ULONG)ixmax*j+i] = 0;
}
mandelcalc();
DosExit(EXIT_THREAD,0);
}
MRESULT EXPENTRY wndproc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
{
int i;
static UCHAR start;
char *stk;
switch (msg)
{
case WM_CREATE:
hwndclient = hwnd;
initcolors();
atexit(leave);
CREATETHREAD(thread, (PUSHORT)&i, stk, 4096);
DosSetPrty(2,1, 0,i);
break;
case WM_SETFOCUS:
active = SHORT1FROMMP(mp2);
focusevent(active);
return 0L;
case WM_SIZE:
cx = SHORT1FROMMP(mp2);
cy = SHORT2FROMMP(mp2);
break;
case WM_PAINT:
WinBeginPaint(hwnd, hps, NULL);
redraw(0);
WinEndPaint(hps);
break;
case WM_CHAR:
key = charfrommsg(mp1,mp2);
if (key)
keyevent(key);
return 0;
case WM_DESTROY:
showhide(NULL, 0);
hwndframe = NULL;
GpiAssociate(hps,NULL);
GpiDestroyPS(hps);
break;
}
return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
}
focusevent(int active)
{
if (!sem)
return 0;
}
keyevent(USHORT key)
{
switch (key & 0xFF)
{
case 27:
exit(1);
break;
}
}
plot(int x, int y, UCHAR color)
{
POINTL ptl;
ptl.x = x;
ptl.y = y;
GpiSetColor(hps,ctbl[color&(ncolors-1)].mask);
GpiSetPel(hps, &ptl);
}
#else
dosdelay(USHORT i)
{
time_t t;
t = clock();
while (clock() -t < (ULONG)i) ;
}
restore()
{
_setvideomode(_DEFAULTMODE);
}
is80x87() /* DOES NOT WORK ON AN XT !!!! */
{
int i;
_asm
{
int 11h
mov [i],ax
}
return i & 2;
}
main(int argc, char **argv)
{
int i, mode=_VRES16COLOR;
arg_c = argc; arg_v = argv;
bitmap = (void far*)(0xA0000000);
if (arg_c < 2)
{
printf("MANDEL mandelbrot program.\n");
printf("Usage: mandel <options>\n");
printf("-l: draws a fern leaf\n");
printf("-innn: maximum number of iterations (%d..%d)\n",MAXITER_MIN, MAXITER_MAX);
printf("-f: Use 320x200x256\n");
if (is80x87())
printf("Math coprocessor installed.\n");
else
printf("No Math coprocessor found (or an XT): it will take H O U R S !!\n");
exit(0);
}
/* freopen("lo","w",stdout); */
ixmax = 640;
iymax = 480;
if (argoption('f'))
{
ixmax = 320;
iymax = 200;
ncolors = 256;
mode = _MRES256COLOR;
}
onexit(restore);
_setvideomode(mode);
xscreen = ixmax;
yscreen = iymax;
mandelcalc();
}
#endif
int argoption(char letter)
{
char c,d;
int j;
for (j=1; j<arg_c; j++)
{
c = arg_v[j][0]; d = toupper(arg_v[j][1]);
if ((c == '/' || c == '-') && d == toupper(letter))
return(j);
}
return(0);
}
ULONG mixcolor(COLORS color1, COLORS color2, int x1, int x2, int xx,
USHORT max)
{
int i,tot,diff;
COLORS result;
tot = x2-x1;
diff = xx-x1;
for (i=0; i<3; i++)
{
result.array[i] = (((int)color2.array[i]-(int)color1.array[i])*diff/tot)
+(int)color1.array[i];
if (result.array[i] >= max) result.array[i] = max-1;
}
return result.mask;
}
void init()
{
range = 0.2;
delta_x = (range / MAX_X);
delta_y = (range / MAX_Y);
y=x=0;
/* fijne mandelbrot (x,y) coordinaten voor mooie plaatjes */
/* x_coord = -0.25; */
/* y_coord = 1.13; */
/* x_coord = -0.20; */
/* y_coord = 0.9950; */
x_coord = -0.15;
y_coord = 0.995;
}
static real AAA[] = { 0, .20, -.15, .85 };
static real CCC[] = { 0, .23, .26, -.04 };
static real DDD[] = { .16, .22, .24, .85 };
static real EEE[] = { 0, .00, .00, .00 };
static real FFF[] = { 0, 1.6 , .44, 1.6 };
static real BBB[] = { 0, -.26, .28, .04 };
static real PPP[] = { .01, .08, .15, 1.0 };
fern()
{
real ran,x,y,xnew,ynew;
int i,k,zmax, smax,ix,iy;
sem = 1;
palflag = 0;
zmax = yscreen/10;
smax = xscreen/10;
x = y = 0.;
for (i=0; i<25000; i++)
{
ran = (real)rand()/32768.;
if (ran < PPP[0])
k = 0;
else if (ran < PPP[1])
k = 1;
else if (ran < PPP[2])
k = 2;
else if (ran < PPP[3])
k = 3;
else
continue;
/* k = 4; */
xnew = AAA[k]*x + BBB[k] *y + EEE[k];
ynew = CCC[k]*x + DDD[k] *y + FFF[k];
x = xnew; y = ynew;
ix = (USHORT)(x*smax)+xscreen/2;
iy = yscreen-(USHORT)(y*zmax);
if (ix < xscreen && iy < yscreen)
putpixel(ix,iy,10);
if (keypressed())
exit(1);
}
}
mandelcalc()
{
int i,j;
time_t t;
real a,b,ac,bc,M,b1,t1,t2;
int I, color;
if (log = argoption('d'))
freopen("lo","w",stdout);
if (argoption('l'))
{
fern();
return 0;
}
init();
sem=1;
for (i=0; i<ncolors; i++)
p[i] = ctbl[i];
if (i = argoption('i'))
{
i = atoi(arg_v[i]+2);
if (i > MAXITER_MIN && i < MAXITER_MAX)
MAX_ITERATIES = i;
}
for (y=0; y < MAX_Y; y++)
{
bc = (y_coord - (y * delta_y));
t = clock();
for (x=0; x < MAX_X; x++)
{
a = ac =(x_coord + (x * delta_x));
b = bc;
M = 0.0;
I = 0;
color = firstcolor;
do
{
b1 = 2.0 * a * b;
t1 = a*a;
t2 = b*b;
a = t1 - t2 + ac;
b = b1 + bc;
M = t1 + t2;
if (++color > ncolors-firstcolor-1)
color=firstcolor;
}
while (M < MAX_VALUE && ++I < MAX_ITERATIES);
putpixel(x,y,color);
if (keypressed())
exit(1);
} /* while x */
if (log)
printf("time=%.2f seconds\n",(real)(clock()-t)/(real)CLK_TCK);
} /* while y */
sem=2;
delay(-1);
} /* end MandelCalc */