perry (04/25/83)
THIS IS A SECOND POSTING - SEEMS A LOT OF FOLKS MISSED THE FIRST.
perry s kivolowitz
There has been a lot of requests on net.micro for a filling algorithm which
would handle arbitrary polygons. A while back I needed a quick and dirty
black and white flooder so I reached for my nearest set of Siggraph
Proceedings and Notes (I thought everybody had a ``nearest set of Siggraph
Proceedings...), turned to any one of several articles by A. R. Smith
(formerly of NYIT now at that great graphics lab on Tatooine) and perverted
what lay therein. So, with the caveat that this code was not intended for
any other eyes other than those residing on the first board on the left in
the cpu bucket, here's der code.
----------------------------------------------------------------------------
Meant to run with an off bus frame buffer - most of the code is there to
cache scan lines (to reduce i/o overhead). Also, there is some code left
in here from some other diddling I was doing at about the same time (so
lint might find some unused routines).
----------------------------------------------------------------------------
#include <stdio.h>
/*
permission is hereby granted to copy this code where ever you like
just as long as you bow down and utter thanks in the direction of
Lucasfilm. In most parts of the country that will cause your
posterior to face Stony Brook, but thats ok with me.
perry s. kivolowitz
allegra!sbcs!perry
perry@suny-sbcs
*/
#define LEFT 0
#define RIGHT 511
#define TOP 511
#define BOTTOM 0
#define STACK_LIMIT 100
#define STACKNOTEMPTY (sp > stack)
struct frame {
int x;
int y;
};
struct frame stack[STACK_LIMIT] , *sp;
int x , y , lx , rx , yref , lxref , rxref;
int new , old;
push()
{
if (sp - stack >= STACK_LIMIT) {
printf("Ooops! Stack Overflow\n");
exit();
}
sp->x = x;
sp->y = y;
sp++;
}
pop()
{
if (--sp < stack) {
printf("Ooops! Stack Underflow\n");
exit();
}
x = sp->x;
y = sp->y;
}
init_stack()
{
sp = stack;
}
dump_stack()
{
struct frame *tsp;
tsp = stack;
printf("Stack Dump:\n");
while (tsp != sp) {
printf("x: %3d y: %3d\n" , tsp->x , tsp->y);
tsp++;
}
}
static last_y = -1;
static last_left = 0; last_right = 511;
static dirty_line = 0;
static short int scan_line[512];
get()
{
register int i;
if (last_y != y) {
last_left = last_left < 0 ? 0 : last_left;
last_left = last_left > 511 ? 511 : last_left;
last_right = last_right < 0 ? 0 : last_right;
last_right = last_right > 511 ? 511 : last_right;
if (dirty_line)
gcwlw(scan_line + last_left ,
last_left ,
last_y ,
last_right - last_left + 1 ,
0 , 0 , 13 , 0
);
dirty_line = 0;
if (last_y != -1) {
last_left = lx;
last_right = rx;
}
gcrlw(last_left ,
y ,
last_right - last_left + 1 ,
1 , scan_line+last_left
);
}
if (x < last_left) {
i = last_left / 2; /* shift right by 2 to the 0 bits */
i = x < i ? x : i;
gcrlw(i , y , last_left - i , 1 , scan_line + i);
last_left = i;
}
if (x > last_right) {
i = last_right + (511 - last_right) / 2;
i = x > i ? x : i;
gcrlw(last_right + 1 , y , i - last_right , 1 ,
scan_line + last_right + 1
);
last_right = i;
}
last_y = y;
return((int) scan_line[x]);
}
set()
{
scan_line[x] = new;
dirty_line = 1;
}
basic_fill(seed_x , seed_y , new_pv)
int seed_x , seed_y , new_pv;
{
x = seed_x;
y = seed_y;
new = new_pv;
old = get();
if (old == new) return;
yref = y;
push();
while (STACKNOTEMPTY) {
pop();
if (get() == new) continue;
fill_line();
if (hi_neighbor()) {
/* printf("Hi_Neighbor True\n"); */
scan_hi();
}
else if (lo_neighbor()) {
/* printf("Hi_Neighbor False\n");
printf("Lo_Neighbor True\n"); */
scan_low();
}
else {
/* printf("Both Hi and Lo are False\n"); */
scan_hi();
scan_low();
}
yref = y;
lxref = lx;
rxref = rx;
}
}
hi_neighbor()
{
if ((y == yref + 1) &&
(lx >= lxref - 1) &&
(rx <= rxref +1))
return(1);
else
return(0);
}
lo_neighbor()
{
if ((y == yref - 1) &&
(lx >= lxref - 1) &&
(rx <= rxref +1))
return(1);
else
return(0);
}
fill_line()
{
fill_right();
fill_left();
}
fill_right()
{
auto int tx = x;
while ((get() == old) && (x <= RIGHT)) {
set();
x++;
}
rx = x - 1;
x = tx;
}
fill_left()
{
auto int tx = x;
x--;
while ((get() == old) && (x >= LEFT)) {
set();
x--;
}
lx = x + 1;
x = tx;
}
scan_hi()
{
auto int tx = x , ty = y;
/* printf("Greetings from sunny scan_hi!\n"); */
if ((y + 1) > TOP) {
/* printf("scan_hi taking y+1 > top return\n"); */
return;
}
x = lx;
y++;
while (x <= rx) {
while ((get() != old) && (x <= rx)) x++;
if (x > rx) {
/* printf("scan_hi taking x > rx break\n"); */
break;
}
push();
while ((get() == old) && (x <= rx)) x++;
}
/* printf("scan_hi leaving via bottom of me\n"); */
x = tx;
y = ty;
}
scan_low()
{
auto int tx = x , ty = y;
if ((y - 1) < BOTTOM) return;
x = lx;
y--;
while (x <= rx) {
while ((get() != old) && (x <= rx)) x++;
if (x > rx) break;
push();
while ((get() == old) && (x <= rx)) x++;
}
x = tx;
y = ty;
}
gcwlw(data,x,y,l,dw,dh,cm,zc)
short data[],x,y,l,dw,dh,cm,zc;
{
grwlw_(data,&x , &y , &l , &dw , &dh , &cm , &zc);
}
snap_stack()
{
printf("X: %3d Y: %3d SP: %3d\n" , x , y , sp - stack);
}