📄 fracsubr.c
字号:
*/
/* sleep N * a tenth of a millisecond */
void sleepms(long ms)
{
extern int tabmode;
static long scalems=0L;
int savehelpmode,savetabmode;
struct timeb t1,t2;
#define SLEEPINIT 250 /* milliseconds for calibration */
savetabmode = tabmode;
savehelpmode = helpmode;
tabmode = 0;
helpmode = -1;
if(scalems==0L) /* calibrate */
{
/* selects a value of scalems that makes the units
10000 per sec independent of CPU speed */
char msg[80];
long millisecs;
int i,elapsed;
scalems = 1L;
if(keypressed()) /* check at start, hope to get start of timeslice */
goto sleepexit;
/* calibrate, assume slow computer first */
do
{
scalems *= 2;
ftime(&t2);
do { /* wait for the start of a new tick */
ftime(&t1);
}
while (t2.time == t1.time && t2.millitm == t1.millitm);
sleepms(10L * SLEEPINIT); /* about 1/4 sec */
ftime(&t2);
if(keypressed()) {
scalems = 0L;
goto sleepexit;
}
}
while ((elapsed = (int)(t2.time-t1.time)*1000 + t2.millitm-t1.millitm)
< SLEEPINIT);
/* once more to see if faster (eg multi-tasking) */
do { /* wait for the start of a new tick */
ftime(&t1);
}
while (t2.time == t1.time && t2.millitm == t1.millitm);
sleepms(10L * SLEEPINIT);
ftime(&t2);
if ((i = (int)(t2.time-t1.time)*1000 + t2.millitm-t1.millitm) < elapsed)
elapsed = (i == 0) ? 1 : i;
scalems = (float)SLEEPINIT/(float)(elapsed) * scalems;
if (debugflag == 700) {
sprintf(msg,"scale factor=%ld",scalems);
stopmsg(0,msg);
}
}
if(ms > 10L * SLEEPINIT) { /* using ftime is probably more accurate */
ms /= 10;
ftime(&t1);
while(1) {
if(keypressed()) break;
ftime(&t2);
if ((t2.time-t1.time)*1000 + t2.millitm-t1.millitm >= ms) break;
}
}
else
if(!keypressed()) {
ms *= scalems;
while(ms-- >= 0);
}
sleepexit:
tabmode = savetabmode;
helpmode = savehelpmode;
}
static void _fastcall plotdorbit(double dx, double dy, int color)
{
int i, j, c;
int save_sxoffs,save_syoffs;
if (orbit_ptr >= 1500) return;
i = dy * plotmx1 - dx * plotmx2; i += sxoffs;
if (i < 0 || i >= sxdots) return;
j = dx * plotmy1 - dy * plotmy2; j += syoffs;
if (j < 0 || j >= sydots) return;
save_sxoffs = sxoffs;
save_syoffs = syoffs;
sxoffs = syoffs = 0;
/* save orbit value */
if(color == -1)
{
*(save_orbit + orbit_ptr++) = i;
*(save_orbit + orbit_ptr++) = j;
*(save_orbit + orbit_ptr++) = c = getcolor(i,j);
putcolor(i,j,c^orbit_color);
}
else
putcolor(i,j,color);
sxoffs = save_sxoffs;
syoffs = save_syoffs;
if(orbit_delay > 0)
sleepms(orbit_delay);
if(soundflag==1)
snd((int)(i*1000/xdots+basehertz));
else if(soundflag > 1)
snd((int)(j*1000/ydots+basehertz));
/* placing sleepms here delays each dot */
}
void iplot_orbit(ix, iy, color)
long ix, iy;
int color;
{
plotdorbit((double)ix/fudge-xxmin,(double)iy/fudge-yymax,color);
}
void plot_orbit(real,imag,color)
double real,imag;
int color;
{
plotdorbit(real-xxmin,imag-yymax,color);
}
void scrub_orbit()
{
static long oldtime = 0;
int i,j,c;
int save_sxoffs,save_syoffs;
save_sxoffs = sxoffs;
save_syoffs = syoffs;
sxoffs = syoffs = 0;
while(orbit_ptr > 0)
{
c = *(save_orbit + --orbit_ptr);
j = *(save_orbit + --orbit_ptr);
i = *(save_orbit + --orbit_ptr);
putcolor(i,j,c);
}
sxoffs = save_sxoffs;
syoffs = save_syoffs;
nosnd();
}
int add_worklist(int xfrom, int xto, int yfrom, int yto, int ybegin,
int pass, int sym)
{
if (num_worklist >= MAXCALCWORK)
return(-1);
worklist[num_worklist].xxstart = xfrom;
worklist[num_worklist].xxstop = xto;
worklist[num_worklist].yystart = yfrom;
worklist[num_worklist].yystop = yto;
worklist[num_worklist].yybegin = ybegin;
worklist[num_worklist].pass = pass;
worklist[num_worklist].sym = sym;
++num_worklist;
tidy_worklist();
return(0);
}
static int _fastcall combine_worklist() /* look for 2 entries which can freely merge */
{
int i,j;
for (i=0; i<num_worklist; ++i)
if (worklist[i].yystart == worklist[i].yybegin)
for (j=i+1; j<num_worklist; ++j)
if (worklist[j].sym == worklist[i].sym
&& worklist[j].yystart == worklist[j].yybegin
&& worklist[i].pass == worklist[j].pass)
{
if ( worklist[i].xxstart == worklist[j].xxstart
&& worklist[i].xxstop == worklist[j].xxstop)
{
if (worklist[i].yystop+1 == worklist[j].yystart)
{
worklist[i].yystop = worklist[j].yystop;
return(j);
}
if (worklist[j].yystop+1 == worklist[i].yystart)
{
worklist[i].yystart = worklist[j].yystart;
worklist[i].yybegin = worklist[j].yybegin;
return(j);
}
}
if ( worklist[i].yystart == worklist[j].yystart
&& worklist[i].yystop == worklist[j].yystop)
{
if (worklist[i].xxstop+1 == worklist[j].xxstart)
{
worklist[i].xxstop = worklist[j].xxstop;
return(j);
}
if (worklist[j].xxstop+1 == worklist[i].xxstart)
{
worklist[i].xxstart = worklist[j].xxstart;
return(j);
}
}
}
return(0); /* nothing combined */
}
void tidy_worklist() /* combine mergeable entries, resort */
{
int i,j;
struct workliststuff tempwork;
while (i=combine_worklist())
{ /* merged two, delete the gone one */
while (++i < num_worklist)
worklist[i-1] = worklist[i];
--num_worklist;
}
for (i=0; i<num_worklist; ++i)
for (j=i+1; j<num_worklist; ++j)
if (worklist[j].pass < worklist[i].pass
|| (worklist[j].pass == worklist[i].pass
&& (worklist[j].yystart < worklist[i].yystart
|| ( worklist[j].yystart == worklist[i].yystart
&& worklist[j].xxstart < worklist[i].xxstart))))
{ /* dumb sort, swap 2 entries to correct order */
tempwork = worklist[i];
worklist[i] = worklist[j];
worklist[j] = tempwork;
}
}
void get_julia_attractor (double real, double imag)
{
_LCMPLX lresult;
_CMPLX result;
int savper,savmaxit;
int i;
if (attractors == 0 && finattract == 0) /* not magnet & not requested */
return;
if (attractors >= N_ATTR) /* space for more attractors ? */
return; /* Bad luck - no room left ! */
savper = periodicitycheck;
savmaxit = maxit;
periodicitycheck = 0;
old.x = real; /* prepare for f.p orbit calc */
old.y = imag;
tempsqrx = sqr(old.x);
tempsqry = sqr(old.y);
lold.x = real; /* prepare for int orbit calc */
lold.y = imag;
ltempsqrx = tempsqrx;
ltempsqry = tempsqry;
lold.x = lold.x << bitshift;
lold.y = lold.y << bitshift;
ltempsqrx = ltempsqrx << bitshift;
ltempsqry = ltempsqry << bitshift;
if (maxit < 500) /* we're going to try at least this hard */
maxit = 500;
color = 0;
while (++color < maxit)
if(curfractalspecific->orbitcalc())
break;
if (color >= maxit) /* if orbit stays in the lake */
{
if (integerfractal) /* remember where it went to */
lresult = lnew;
else
result = new;
for (i=0;i<10;i++) {
if(!curfractalspecific->orbitcalc()) /* if it stays in the lake */
{ /* and doen't move far, probably */
if (integerfractal) /* found a finite attractor */
{
if(labs(lresult.x-lnew.x) < lclosenuff
&& labs(lresult.y-lnew.y) < lclosenuff)
{
lattr[attractors] = lnew;
attrperiod[attractors] = i+1;
attractors++; /* another attractor - coloured lakes ! */
break;
}
}
else
{
if(fabs(result.x-new.x) < closenuff
&& fabs(result.y-new.y) < closenuff)
{
attr[attractors] = new;
attrperiod[attractors] = i+1;
attractors++; /* another attractor - coloured lakes ! */
break;
}
}
} else {
break;
}
}
}
if(attractors==0)
periodicitycheck = savper;
maxit = savmaxit;
}
#define maxyblk 7 /* must match calcfrac.c */
#define maxxblk 202 /* must match calcfrac.c */
int ssg_blocksize() /* used by solidguessing and by zoom panning */
{
int blocksize,i;
/* blocksize 4 if <300 rows, 8 if 300-599, 16 if 600-1199, 32 if >=1200 */
blocksize=4;
i=300;
while(i<=ydots)
{
blocksize+=blocksize;
i+=i;
}
/* increase blocksize if prefix array not big enough */
while(blocksize*(maxxblk-2)<xdots || blocksize*(maxyblk-2)*16<ydots)
blocksize+=blocksize;
return(blocksize);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -