-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfractint.c
296 lines (258 loc) · 11 KB
/
fractint.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/*
fracint
https://en.wikibooks.org/wiki/Fractals/fractint
https://en.wikipedia.org/wiki/Fractint
https://www.fractint.org/
CALCFRAC.C contains the high level ("engine") code for calculating the
fractal images (well, SOMEBODY had to do it!).
Original author Tim Wegner, but just about ALL the authors have contributed
SOME code to this routine at one time or another, or contributed to one of
the many massive restructurings.
The following modules work very closely with CALCFRAC.C:
FRACTALS.C the fractal-specific code for escape-time fractals.
FRACSUBR.C assorted subroutines belonging mainly to calcfrac, like add_worklist
CALCMAND.ASM fast Mandelbrot/Julia integer implementation
Additional fractal-specific modules are also invoked from CALCFRAC:
LORENZ.C engine level and fractal specific code for attractors.
JB.C julibrot logic
PARSER.C formula fractals
and more
-------------------------------------------------------------------- */
/******************* boundary trace method ***************************
Fractint's original btm was written by David Guenther. There were a few
rare circumstances in which the original btm would not trace or fill
correctly, even on Mandelbrot Sets. The code below was adapted from
"Mandelbrot Sets by Wesley Loewer" (see calmanfp.asm) which was written
before I was introduced to Fractint. It should be noted that without
David Guenther's implimentation of a btm, I doubt that I would have been
able to impliment my own code into Fractint. There are several things in
the following code that are not original with me but came from David
Guenther's code. I've noted these places with the initials DG.
Wesley Loewer 3/8/92
*********************************************************************/
#define bkcolor 0 /* I have some ideas for the future with this. -Wes */
#define advance_match() coming_from = ((going_to = (going_to - 1) & 0x03) - 1) & 0x03
#define advance_no_match() going_to = (going_to + 1) & 0x03
/***** vars for new btm *****/
enum direction {North,East,South,West};
enum direction going_to;
int trail_row, trail_col;
/*******************************************************************/
/* take one step in the direction of going_to */
static void step_col_row()
{
switch (going_to)
{
case North:
col = trail_col;
row = trail_row - 1;
break;
case East:
col = trail_col + 1;
row = trail_row;
break;
case South:
col = trail_col;
row = trail_row + 1;
break;
case West:
col = trail_col - 1;
row = trail_row;
break;
}
}
static
int bound_trace_main(void)
{
enum direction coming_from;
unsigned int match_found, continue_loop;
int trail_color, fillcolor_used, last_fillcolor_used = -1;
int max_putline_length;
int right, left, length;
static FCODE btm_cantbeused[]={"Boundary tracing cannot be used with "};
if (inside == 0 || outside == 0)
{
static FCODE inside_outside[] = {"inside=0 or outside=0"};
char msg[MSGLEN];
far_strcpy(msg,btm_cantbeused);
far_strcat(msg,inside_outside);
stopmsg(0,msg);
return(-1);
}
if (colors < 16)
{
char msg[MSGLEN];
static FCODE lessthansixteen[] = {"< 16 colors"};
far_strcpy(msg,btm_cantbeused);
far_strcat(msg,lessthansixteen);
stopmsg(0,msg);
return(-1);
}
got_status = 2;
max_putline_length = 0; /* reset max_putline_length */
for (currow = iystart; currow <= iystop; currow++)
{
reset_periodicity = 1; /* reset for a new row */
color = bkcolor;
for (curcol = ixstart; curcol <= ixstop; curcol++)
{
if (getcolor(curcol, currow) != bkcolor)
continue;
trail_color = color;
row = currow;
col = curcol;
if ((*calctype)()== -1) /* color, row, col are global */
{
if (showdot != bkcolor) /* remove showdot pixel */
(*plot)(col,row,bkcolor);
if (iystop != yystop) /* DG */
iystop = yystop - (currow - yystart); /* allow for sym */
add_worklist(xxstart,xxstop,curcol,currow,iystop,currow,0,worksym);
return -1;
}
reset_periodicity = 0; /* normal periodicity checking */
/*
This next line may cause a few more pixels to be calculated,
but at the savings of quite a bit of overhead
*/
if (color != trail_color) /* DG */
continue;
/* sweep clockwise to trace outline */
trail_row = currow;
trail_col = curcol;
trail_color = color;
fillcolor_used = fillcolor > 0 ? fillcolor : trail_color;
coming_from = West;
going_to = East;
match_found = 0;
continue_loop = TRUE;
do
{
step_col_row();
if (row >= currow
&& col >= ixstart
&& col <= ixstop
&& row <= iystop)
{
/* the order of operations in this next line is critical */
if ((color = getcolor(col, row)) == bkcolor && (*calctype)()== -1)
/* color, row, col are global for (*calctype)() */
{
if (showdot != bkcolor) /* remove showdot pixel */
(*plot)(col,row,bkcolor);
if (iystop != yystop) /* DG */
iystop = yystop - (currow - yystart); /* allow for sym */
add_worklist(xxstart,xxstop,curcol,currow,iystop,currow,0,worksym);
return -1;
}
else if (color == trail_color)
{
if (match_found < 4) /* to keep it from overflowing */
match_found++;
trail_row = row;
trail_col = col;
advance_match();
}
else
{
advance_no_match();
continue_loop = going_to != coming_from || match_found;
}
}
else
{
advance_no_match();
continue_loop = going_to != coming_from || match_found;
}
} while (continue_loop && (col != curcol || row != currow));
if (match_found <= 3) /* DG */
{ /* no hole */
color = bkcolor;
reset_periodicity = 1;
continue;
}
/*
Fill in region by looping around again, filling lines to the left
whenever going_to is South or West
*/
trail_row = currow;
trail_col = curcol;
coming_from = West;
going_to = East;
do
{
match_found = FALSE;
do
{
step_col_row();
if (row >= currow
&& col >= ixstart
&& col <= ixstop
&& row <= iystop
&& getcolor(col,row) == trail_color)
/* getcolor() must be last */
{
if (going_to == South
|| (going_to == West && coming_from != East))
{ /* fill a row, but only once */
right = col;
while (--right >= ixstart && (color = getcolor(right,row)) == trail_color)
; /* do nothing */
if (color == bkcolor) /* check last color */
{
left = right;
while (getcolor(--left,row) == bkcolor)
/* Should NOT be possible for left < ixstart */
; /* do nothing */
left++; /* one pixel too far */
if (right == left) /* only one hole */
(*plot)(left,row,fillcolor_used);
else
{ /* fill the line to the left */
length=right-left+1;
if (fillcolor_used != last_fillcolor_used || length > max_putline_length)
{ /* only reset dstack if necessary */
memset(dstack,fillcolor_used,length);
last_fillcolor_used = fillcolor_used;
max_putline_length = length;
}
sym_fill_line(row, left, right, dstack);
}
} /* end of fill line */
#if 0 /* don't interupt with a check_key() during fill */
if(--kbdcount<=0)
{
if(check_key())
{
if (iystop != yystop)
iystop = yystop - (currow - yystart); /* allow for sym */
add_worklist(xxstart,xxstop,curcol,currow,iystop,currow,0,worksym);
return(-1);
}
kbdcount=max_kbdcount;
}
#endif
}
trail_row = row;
trail_col = col;
advance_match();
match_found = TRUE;
}
else
advance_no_match();
} while (!match_found && going_to != coming_from);
if (!match_found)
{ /* next one has to be a match */
step_col_row();
trail_row = row;
trail_col = col;
advance_match();
}
} while (trail_col != curcol || trail_row != currow);
reset_periodicity = 1; /* reset after a trace/fill */
color = bkcolor;
}
}
return 0;
}
/******************* end of boundary trace method *******************/