home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gdead.berkeley.edu
/
gdead.berkeley.edu.tar
/
gdead.berkeley.edu
/
pub
/
cad-tools
/
ciftomann.tar
/
resort.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-28
|
4KB
|
191 lines
#include "ciftomann.h"
#include "fd.h"
#include <stdio.h>
int max_index = 100;
#define READ_EDGE(edgeptr) {\
if ( fread(edgeptr, sizeof(EDGE), 1, stdin) == 0) {\
eof = TRUE;\
}\
}
typedef struct {
EDGE *array;
int index;
} window;
window *temp;
#define EXCHANGE(a,b) { temp = a; a = b; b = temp; }
typedef enum { FALSE = 0,TRUE } boolean;
boolean eof;
EDGE start; /* the first edge loaded by load */
int min; /* the top of the new low window */
int delta; /* the grow/shrink factor */
int comparer();
/*
* resort is used to resort edges if we have put them out
* of order by doing a grow/shrink of delta. The method of
* sorting relies on the fact that elements are at most
* 2*delta units apart. We therefore sort incoming edges
* into two different windows: edges falling in the ystart
* to ystart + delta going into one window and edges falling
* into the ystart + delta to ystart + 2*delta go into the
* second window. Once we see an edge beyond ystart + 2*delta,
* we know there are no more edges coming that would lie in the
* first window. We can therefore sort the first window, output
* it, swap the two windows, set ystart = ystart+delta, and
* continue the process.
*/
main(argc,argv)
int argc;
char **argv;
{
window window_1,window_2;
window *low = &window_1,
*high = &window_2;;
sscanf(argv[1],"%d",&delta);
delta = Abs(delta);
READ_EDGE(&start);
if ( eof ) {
exit(0);
}
if ( delta > 0 ) {
min = start.y;
allocate(low,high);
while ( !eof ) {
load(low,high); /* read edges into the windows until
a 2*delta range has been seen */
/* sort the first window */
qsort(low->array,low->index,sizeof(EDGE),comparer);
output(low);
EXCHANGE(low,high); /* swap the low and high windows */
}
/* sort the final window */
qsort(low->array,low->index,sizeof(EDGE),comparer);
output(low);
} else {
/* there was no grow/shrink so copy the edges
out directly */
while ( !eof ) {
fwrite(&start, sizeof(EDGE), 1, stdout);
READ_EDGE(&start);
}
}
exit(0);
}
/* sort the incoming edges into the two windows, see the opening
* comment */
load(low,high)
window *low,*high;
{
EDGE current;
int ysplit,ystop;
current = start;
ysplit = start.y;
ystop = start.y + 2*delta;
do {
if (current.y < ysplit) {
if (low->index >= max_index) {
reallocate(low, high);
}
low->array[low->index++] = current;
} else {
if (high->index >= max_index) {
reallocate(low, high);
}
high->array[high->index++] = current;
}
if ( current.y < min ) {
min = current.y;
}
READ_EDGE(¤t);
} while (current.y < ystop && !eof);
start = current;
}
output(hi)
window *hi;
{
register int i,max;
register EDGE *array;
max = hi->index;
array = hi->array;
for (i = 0; i < max; i++) {
fwrite((char *) (array+i), sizeof(EDGE), 1, stdout);
}
hi->index = 0;
}
allocate(a,b)
window *a,*b;
{
a->array = (EDGE *) malloc(max_index*sizeof(EDGE));
b->array = (EDGE *) malloc(max_index*sizeof(EDGE));
if (a->array == (EDGE *) 0 || b->array == (EDGE *) 0) {
panic("can't obtain any memory");
}
a->index = 0;
b->index = 0;
}
char *realloc();
reallocate(a,b)
window *a, *b;
{
max_index *= 2;
free(a->array);
a->array = (EDGE *) realloc((char *) a->array,
max_index*sizeof(EDGE));
free(b->array);
b->array = (EDGE *) realloc((char *) b->array,
max_index*sizeof(EDGE));
if (a->array == (EDGE *) 0 || b->array == (EDGE *) 0) {
panic("can't obtain any memory");
}
}
panic(str)
char *str;
{
fprintf(stderr,"Panic in resort: %s\n",str);
exit(1);
}