home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Computerworld 1996 March
/
Computerworld_1996-03_cd.bin
/
idg_cd3
/
grafika
/
fraktaly
/
frasr192
/
lsysf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-12
|
17KB
|
688 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef __TURBOC__
#include <alloc.h>
#else
#include <malloc.h>
#endif
#include "fractint.h"
#include "prototyp.h"
#include "lsys.h"
#ifdef max
#undef max
#endif
struct lsys_cmd {
void (*f)(struct lsys_turtlestatef *);
int ptype;
union {
long n;
LDBL nf;
} parm;
char ch;
};
#define sins_f ((LDBL *)(boxy))
#define coss_f (((LDBL *)(boxy)+50))
static struct lsys_cmd far * _fastcall findsize(struct lsys_cmd far *,struct lsys_turtlestatef *, struct lsys_cmd far **,int);
/* Define blanks for portability */
#ifdef XFRACT
void lsysf_prepfpu(struct lsys_turtlestatef *x) { }
void lsysf_donefpu(struct lsys_turtlestatef *x) { }
#endif
#ifdef XFRACT
static void lsysf_doplus(struct lsys_turtlestatef *cmd)
{
if (cmd->reverse) {
if (++cmd->angle == cmd->maxangle)
cmd->angle = 0;
}
else {
if (cmd->angle)
cmd->angle--;
else
cmd->angle = cmd->dmaxangle;
}
}
#else
extern void lsysf_doplus(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
/* This is the same as lsys_doplus, except maxangle is a power of 2. */
static void lsysf_doplus_pow2(struct lsys_turtlestatef *cmd)
{
if (cmd->reverse) {
cmd->angle++;
cmd->angle &= cmd->dmaxangle;
}
else {
cmd->angle--;
cmd->angle &= cmd->dmaxangle;
}
}
#else
extern void lsysf_doplus_pow2(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dominus(struct lsys_turtlestatef *cmd)
{
if (cmd->reverse) {
if (cmd->angle)
cmd->angle--;
else
cmd->angle = cmd->dmaxangle;
}
else {
if (++cmd->angle == cmd->maxangle)
cmd->angle = 0;
}
}
#else
extern void lsysf_dominus(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dominus_pow2(struct lsys_turtlestatef *cmd)
{
if (cmd->reverse) {
cmd->angle--;
cmd->angle &= cmd->dmaxangle;
}
else {
cmd->angle++;
cmd->angle &= cmd->dmaxangle;
}
}
#else
extern void lsysf_dominus_pow2(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_doslash(struct lsys_turtlestatef *cmd)
{
if (cmd->reverse)
cmd->realangle -= cmd->parm.nf;
else
cmd->realangle += cmd->parm.nf;
}
#else
extern void lsysf_doslash(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dobslash(struct lsys_turtlestatef *cmd)
{
if (cmd->reverse)
cmd->realangle += cmd->parm.nf;
else
cmd->realangle -= cmd->parm.nf;
}
#else
extern void lsysf_dobslash(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_doat(struct lsys_turtlestatef *cmd)
{
cmd->size *= cmd->parm.nf;
}
#else
extern void lsysf_doat(struct lsys_turtlestatef *cmd, long n);
#endif
static void
lsysf_dopipe(struct lsys_turtlestatef *cmd)
{
cmd->angle = (char)(cmd->angle + cmd->maxangle / 2);
cmd->angle %= cmd->maxangle;
}
#ifdef XFRACT
static void lsysf_dopipe_pow2(struct lsys_turtlestatef *cmd)
{
cmd->angle += cmd->maxangle >> 1;
cmd->angle &= cmd->dmaxangle;
}
#else
extern void lsysf_dopipe_pow2(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dobang(struct lsys_turtlestatef *cmd)
{
cmd->reverse = ! cmd->reverse;
}
#else
extern void lsysf_dobang(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dosizedm(struct lsys_turtlestatef *cmd)
{
double angle = (double) cmd->realangle;
double s, c;
s = sin(angle);
c = cos(angle);
cmd->xpos += cmd->size * cmd->aspect * c;
cmd->ypos += cmd->size * s;
if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
}
#else
extern void lsysf_dosizedm(struct lsys_turtlestatef *cmd, long n);
#endif
#ifdef XFRACT
static void lsysf_dosizegf(struct lsys_turtlestatef *cmd)
{
cmd->xpos += cmd->size * coss_f[cmd->angle];
cmd->ypos += cmd->size * sins_f[cmd->angle];
if (cmd->xpos>cmd->xmax) cmd->xmax=cmd->xpos;
if (cmd->ypos>cmd->ymax) cmd->ymax=cmd->ypos;
if (cmd->xpos<cmd->xmin) cmd->xmin=cmd->xpos;
if (cmd->ypos<cmd->ymin) cmd->ymin=cmd->ypos;
}
#else
extern void lsysf_dosizegf(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dodrawd(struct lsys_turtlestatef *cmd)
{
double angle = (double) cmd->realangle;
double s, c;
int lastx, lasty;
s = sin(angle);
c = cos(angle);
lastx=(int) cmd->xpos;
lasty=(int) cmd->ypos;
cmd->xpos += cmd->size * cmd->aspect * c;
cmd->ypos += cmd->size * s;
draw_line(lastx, lasty, (int) cmd->xpos, (int) cmd->ypos, cmd->curcolor);
}
#else
extern void lsysf_dodrawd(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dodrawm(struct lsys_turtlestatef *cmd)
{
double angle = (double) cmd->realangle;
double s, c;
s = sin(angle);
c = cos(angle);
cmd->xpos += cmd->size * cmd->aspect * c;
cmd->ypos += cmd->size * s;
}
#else
extern void lsysf_dodrawm(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dodrawg(struct lsys_turtlestatef *cmd)
{
cmd->xpos += cmd->size * coss_f[cmd->angle];
cmd->ypos += cmd->size * sins_f[cmd->angle];
}
#else
extern void lsysf_dodrawg(struct lsys_turtlestatef *cmd);
#endif
#ifdef XFRACT
static void lsysf_dodrawf(struct lsys_turtlestatef *cmd)
{
int lastx = (int) cmd->xpos;
int lasty = (int) cmd->ypos;
cmd->xpos += cmd->size * coss_f[cmd->angle];
cmd->ypos += cmd->size * sins_f[cmd->angle];
draw_line(lastx,lasty,(int) cmd->xpos, (int) cmd->ypos, cmd->curcolor);
}
#else
extern void lsysf_dodrawf(struct lsys_turtlestatef *cmd);
#endif
static void lsysf_dodrawc(struct lsys_turtlestatef *cmd)
{
cmd->curcolor = (char)(((int) cmd->parm.n) % colors);
}
static void lsysf_dodrawgt(struct lsys_turtlestatef *cmd)
{
cmd->curcolor = (char)(cmd->curcolor - cmd->parm.n);
if ((cmd->curcolor %= colors) == 0)
cmd->curcolor = (char)(colors-1);
}
static void lsysf_dodrawlt(struct lsys_turtlestatef *cmd)
{
cmd->curcolor = (char)(cmd->curcolor + cmd->parm.n);
if ((cmd->curcolor %= colors) == 0)
cmd->curcolor = 1;
}
static struct lsys_cmd far * _fastcall
findsize(struct lsys_cmd far *command, struct lsys_turtlestatef *ts, struct lsys_cmd far **rules, int depth)
{
struct lsys_cmd far **rulind;
int tran;
if (overflow) /* integer math routines overflowed */
return NULL;
#ifndef __TURBOC__
if (stackavail() < 400) { /* leave some margin for calling subrtns */
ts->stackoflow = 1;
return NULL;
}
#endif
while (command->ch && command->ch !=']') {
if (! (ts->counter++)) {
/* let user know we're not dead */
if (thinking(1,"L-System thinking (higher orders take longer)")) {
ts->counter--;
return NULL;
}
}
tran=0;
if (depth) {
for(rulind=rules;*rulind;rulind++)
if ((*rulind)->ch==command->ch) {
tran=1;
if (findsize((*rulind)+1,ts,rules,depth-1) == NULL)
return(NULL);
}
}
if (!depth || !tran) {
if (command->f) {
switch (command->ptype) {
case 4:
ts->parm.n = command->parm.n;
break;
case 10:
ts->parm.nf = command->parm.nf;
break;
default:
break;
}
(*command->f)(ts);
}
else if (command->ch == '[') {
char saveang,saverev;
LDBL savesize,savex,savey,saverang;
lsys_donefpu(ts);
saveang=ts->angle;
saverev=ts->reverse;
savesize=ts->size;
saverang=ts->realangle;
savex=ts->xpos;
savey=ts->ypos;
lsys_prepfpu(ts);
if ((command=findsize(command+1,ts,rules,depth)) == NULL)
return(NULL);
lsys_donefpu(ts);
ts->angle=saveang;
ts->reverse=saverev;
ts->size=savesize;
ts->realangle=saverang;
ts->xpos=savex;
ts->ypos=savey;
lsys_prepfpu(ts);
}
}
command++;
}
return command;
}
int _fastcall
lsysf_findscale(struct lsys_cmd far *command, struct lsys_turtlestatef *ts, struct lsys_cmd far **rules, int depth)
{
float horiz,vert;
LDBL xmin, xmax, ymin, ymax;
LDBL locsize;
LDBL locaspect;
struct lsys_cmd far *fsret;
locaspect=screenaspect*xdots/ydots;
ts->aspect = locaspect;
ts->xpos =
ts->ypos =
ts->xmin =
ts->xmax =
ts->ymax =
ts->ymin = 0;
ts->angle =
ts->reverse =
ts->counter = 0;
ts->realangle = 0;
ts->size = 1;
lsys_prepfpu(ts);
fsret = findsize(command,ts,rules,depth);
lsys_donefpu(ts);
thinking(0, NULL); /* erase thinking message if any */
xmin = ts->xmin;
xmax = ts->xmax;
ymin = ts->ymin;
ymax = ts->ymax;
/* locsize = ts->size; */
if (fsret == NULL)
return 0;
if (xmax == xmin)
horiz = (float)1E37;
else
horiz = (float)((xdots-10)/(xmax-xmin));
if (ymax == ymin)
vert = (float)1E37;
else
vert = (float)((ydots-6) /(ymax-ymin));
locsize = (vert<horiz) ? vert : horiz;
if (horiz == 1E37)
ts->xpos = xdots/2;
else
/* ts->xpos = -xmin*(locsize)+5+((xdots-10)-(locsize)*(xmax-xmin))/2; */
ts->xpos = (xdots-locsize*(xmax+xmin))/2;
if (vert == 1E37)
ts->ypos = ydots/2;
else
/* ts->ypos = -ymin*(locsize)+3+((ydots-6)-(locsize)*(ymax-ymin))/2; */
ts->ypos = (ydots-locsize*(ymax+ymin))/2;
ts->size = locsize;
return 1;
}
struct lsys_cmd far * _fastcall
drawLSysF(struct lsys_cmd far *command,struct lsys_turtlestatef *ts, struct lsys_cmd far **rules,int depth)
{
struct lsys_cmd far **rulind;
int tran;
if (overflow) /* integer math routines overflowed */
return NULL;
#ifndef __TURBOC__
if (stackavail() < 400) { /* leave some margin for calling subrtns */
ts->stackoflow = 1;
return NULL;
}
#endif
while (command->ch && command->ch !=']') {
if (!(ts->counter++)) {
if (keypressed()) {
ts->counter--;
return NULL;
}
}
tran=0;
if (depth) {
for(rulind=rules;*rulind;rulind++)
if ((*rulind)->ch == command->ch) {
tran=1;
if (drawLSysF((*rulind)+1,ts,rules,depth-1) == NULL)
return NULL;
}
}
if (!depth||!tran) {
if (command->f) {
switch (command->ptype) {
case 4:
ts->parm.n = command->parm.n;
break;
case 10:
ts->parm.nf = command->parm.nf;
break;
default:
break;
}
(*command->f)(ts);
}
else if (command->ch == '[') {
char saveang,saverev,savecolor;
LDBL savesize,savex,savey,saverang;
lsys_donefpu(ts);
saveang=ts->angle;
saverev=ts->reverse;
savesize=ts->size;
saverang=ts->realangle;
savex=ts->xpos;
savey=ts->ypos;
savecolor=ts->curcolor;
lsys_prepfpu(ts);
if ((command=drawLSysF(command+1,ts,rules,depth)) == NULL)
return(NULL);
lsys_donefpu(ts);
ts->angle=saveang;
ts->reverse=saverev;
ts->size=savesize;
ts->realangle=saverang;
ts->xpos=savex;
ts->ypos=savey;
ts->curcolor=savecolor;
lsys_prepfpu(ts);
}
}
command++;
}
return command;
}
struct lsys_cmd far *
LSysFSizeTransform(char far *s, struct lsys_turtlestatef *ts)
{
struct lsys_cmd far *ret;
struct lsys_cmd far *doub;
int max = 10;
int n = 0;
void (*f)();
long num;
int ptype;
double PI180 = PI / 180.0;
void (*plus)() = (ispow2(ts->maxangle)) ? lsysf_doplus_pow2 : lsysf_doplus;
void (*minus)() = (ispow2(ts->maxangle)) ? lsysf_dominus_pow2 : lsysf_dominus;
void (*pipe)() = (ispow2(ts->maxangle)) ? lsysf_dopipe_pow2 : lsysf_dopipe;
void (*slash)() = lsysf_doslash;
void (*bslash)() = lsysf_dobslash;
void (*at)() = lsysf_doat;
void (*dogf)() = lsysf_dosizegf;
ret = (struct lsys_cmd far *) farmemalloc((long) max * sizeof(struct lsys_cmd));
if (ret == NULL) {
ts->stackoflow = 1;
return NULL;
}
while (*s) {
f = NULL;
num = 0;
ptype = 4;
ret[n].ch = *s;
switch (*s) {
case '+': f = plus; break;
case '-': f = minus; break;
case '/': f = slash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
case '\\': f = bslash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
case '@': f = at; ptype = 10; ret[n].parm.nf = getnumber(&s); break;
case '|': f = pipe; break;
case '!': f = lsysf_dobang; break;
case 'd':
case 'm': f = lsysf_dosizedm; break;
case 'g':
case 'f': f = dogf; break;
case '[': num = 1; break;
case ']': num = 2; break;
default:
num = 3;
break;
}
#ifdef XFRACT
ret[n].f = (void (*)())f;
#else
ret[n].f = (void (*)(struct lsys_turtlestatef *))f;
#endif
if (ptype == 4)
ret[n].parm.n = num;
ret[n].ptype = ptype;
if (++n == max) {
doub = (struct lsys_cmd far *) farmemalloc((long) max*2*sizeof(struct lsys_cmd));
if (doub == NULL) {
farmemfree(ret);
ts->stackoflow = 1;
return NULL;
}
far_memcpy(doub, ret, max*sizeof(struct lsys_cmd));
farmemfree(ret);
ret = doub;
max <<= 1;
}
s++;
}
ret[n].ch = 0;
ret[n].f = NULL;
ret[n].parm.n = 0;
n++;
doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
if (doub == NULL) {
farmemfree(ret);
ts->stackoflow = 1;
return NULL;
}
far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
farmemfree(ret);
return doub;
}
struct lsys_cmd far *
LSysFDrawTransform(char far *s, struct lsys_turtlestatef *ts)
{
struct lsys_cmd far *ret;
struct lsys_cmd far *doub;
int max = 10;
int n = 0;
void (*f)();
LDBL num;
int ptype;
LDBL PI180 = PI / 180.0;
void (*plus)() = (ispow2(ts->maxangle)) ? lsysf_doplus_pow2 : lsysf_doplus;
void (*minus)() = (ispow2(ts->maxangle)) ? lsysf_dominus_pow2 : lsysf_dominus;
void (*pipe)() = (ispow2(ts->maxangle)) ? lsysf_dopipe_pow2 : lsysf_dopipe;
void (*slash)() = lsysf_doslash;
void (*bslash)() = lsysf_dobslash;
void (*at)() = lsysf_doat;
void (*drawg)() = lsysf_dodrawg;
ret = (struct lsys_cmd far *) farmemalloc((long) max * sizeof(struct lsys_cmd));
if (ret == NULL) {
ts->stackoflow = 1;
return NULL;
}
while (*s) {
f = NULL;
num = 0;
ptype = 4;
ret[n].ch = *s;
switch (*s) {
case '+': f = plus; break;
case '-': f = minus; break;
case '/': f = slash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
case '\\': f = bslash; ptype = 10; ret[n].parm.nf = getnumber(&s) * PI180; break;
case '@': f = at; ptype = 10; ret[n].parm.nf = getnumber(&s); break;
case '|': f = pipe; break;
case '!': f = lsysf_dobang; break;
case 'd': f = lsysf_dodrawd; break;
case 'm': f = lsysf_dodrawm; break;
case 'g': f = drawg; break;
case 'f': f = lsysf_dodrawf; break;
case 'c': f = lsysf_dodrawc; num = getnumber(&s); break;
case '<': f = lsysf_dodrawlt; num = getnumber(&s); break;
case '>': f = lsysf_dodrawgt; num = getnumber(&s); break;
case '[': num = 1; break;
case ']': num = 2; break;
default:
num = 3;
break;
}
#ifdef XFRACT
ret[n].f = (void (*)())f;
#else
ret[n].f = (void (*)(struct lsys_turtlestatef *))f;
#endif
if (ptype == 4)
ret[n].parm.n = (long)num;
ret[n].ptype = ptype;
if (++n == max) {
doub = (struct lsys_cmd far *) farmemalloc((long) max*2*sizeof(struct lsys_cmd));
if (doub == NULL) {
farmemfree(ret);
ts->stackoflow = 1;
return NULL;
}
far_memcpy(doub, ret, max*sizeof(struct lsys_cmd));
farmemfree(ret);
ret = doub;
max <<= 1;
}
s++;
}
ret[n].ch = 0;
ret[n].f = NULL;
ret[n].parm.n = 0;
n++;
doub = (struct lsys_cmd far *) farmemalloc((long) n*sizeof(struct lsys_cmd));
if (doub == NULL) {
farmemfree(ret);
ts->stackoflow = 1;
return NULL;
}
far_memcpy(doub, ret, n*sizeof(struct lsys_cmd));
farmemfree(ret);
return doub;
}
void _fastcall lsysf_dosincos(void)
{
LDBL locaspect;
LDBL TWOPI = 2.0 * PI;
LDBL twopimax;
LDBL twopimaxi;
int i;
locaspect=screenaspect*xdots/ydots;
twopimax = TWOPI / maxangle;
for(i=0;i<maxangle;i++) {
twopimaxi = i * twopimax;
sins_f[i]= sinl(twopimaxi);
coss_f[i]= locaspect * cosl(twopimaxi);
}
}