home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gdead.berkeley.edu
/
gdead.berkeley.edu.tar
/
gdead.berkeley.edu
/
pub
/
cad-tools
/
ciftomann.tar
/
boxer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-28
|
7KB
|
318 lines
#include "boxer.h"
#include "aeledge.h"
#include "ciftomann.h"
#include <stdio.h>
#include "fd.h"
#include "Out_Box.h"
typedef enum { /* the different types of changes an edge can cause */
BEGIN,
LEFT_GROW,
RIGHT_GROW,
JOIN,
END,
LEFT_SHRINK,
RIGHT_SHRINK,
SPLIT,
BAD_EDGE
} edge_desc;
edge_desc edge_type();
AEL_EDGEPTR MakeEdge();
static AEL_EDGEPTR GetEdge();
char *malloc();
static EmitBox();
static AEL_LIST AEList;
static AEL_EDGE medge;
static AEL_EDGEPTR AEdge,
MEdge;
/*
boxer : reads edges from standard in and through a scan_line
algorithm, breaks up the manhatten geometry into boxes,
writing them on standard output. Both input and output
are in binary, as boxer is designed to be one section
of the ciftomann pipeline, placed between the resorter
and smash
*/
main()
{
int CurrentY;
ProgName = "Boxer";
/* Instead of checking for ends of the doubly linked active
edge list all the time, I put two dummy points in at plus
and minus infinity instead. Hopefully no real coordinate
will be be outside these two points, so I don`t have to
worry about any operations on the endpoints
*/
AEList.top = MakeEdge(-INFINITY,-INFINITY,-INFINITY,1,NIL,NIL);
AEList.bottom = MakeEdge(INFINITY,INFINITY,-INFINITY,1,NIL,NIL);
AEList.bottom->last = AEList.top;
AEList.top->next = AEList.bottom;
MEdge = GetEdge();
AEdge = AEList.top;
if ( MEdge == NIL ) {
exit(0);
}
do {
AEdge = AEList.top;
CurrentY = MEdge->y;
/* Find the proper place in the scanline for the
new edge */
while ( Greater_than_Equal(MEdge->x, AEdge->next->x) ) {
Inc(AEdge);
}
/* Decide what to do on the basis of the change in
geometry caused by the new edge */
switch ( edge_type(MEdge) ) {
case BEGIN :
/* Entering a new region of geometry */
InsertAbove(AEdge->next,MEdge->x,MEdge->xend,
MEdge->y,MEdge->sense);
break;
case LEFT_GROW :
/* the new edge abuts AEdge->next, so
emit a box upto AEdge->next and merge
MEdege and AEdge->next */
EmitBox(AEdge->next,CurrentY);
AEdge->next->x = MEdge->x;
AEdge->next->y = CurrentY;
break;
case RIGHT_GROW :
/* the new edge abuts AEdge, so
emit a box upto AEdge and merge
MEdege and AEdge */
EmitBox(AEdge,CurrentY);
AEdge->xend = MEdge->xend;
AEdge->y = CurrentY;
break;
case JOIN :
/* MEdge abuts AEdge on the left and AEdge->next
on the right, so emit a box for both and merge
the three edges into one */
EmitBox(AEdge,CurrentY);
EmitBox(AEdge->next,CurrentY);
AEdge->xend = AEdge->next->xend;
AEdge->y = CurrentY;
Remove(AEList,AEdge->next);
break;
case END :
/* We have just closed off a piece of geometry
so emit and remove */
EmitBox(AEdge,CurrentY);
AEdge = AEdge->last;
Remove(AEList,AEdge->next);
break;
case LEFT_SHRINK :
/* Medge closed off part of AEdge, so
emit and shrink */
EmitBox(AEdge,CurrentY);
AEdge->x = MEdge->xend;
AEdge->y = CurrentY;
AEdge = AEdge->last;
break;
case RIGHT_SHRINK :
/* Medge closed off part of AEdge, so
emit and shrink */
EmitBox(AEdge,CurrentY);
AEdge->xend = MEdge->x;
AEdge->y = CurrentY;
break;
case SPLIT :
/* MEdge splits AEdge into two fragements,
so emit and split */
EmitBox(AEdge,CurrentY);
InsertAbove(AEdge->next,MEdge->xend,AEdge->xend,
CurrentY,UP);
AEdge->xend = MEdge->x;
AEdge->y = CurrentY;
break;
case BAD_EDGE :
/* Something impossible has happened, blame
grow shrink and exit */
fprintf(stderr,"Error : possible bad grow/shrink around x = %d to %d, y = %d\n",MEdge->x,MEdge->xend,MEdge->y);
exit(1);
break;
default :
panic("Impossible return from edge_type");
} /* end of case */
MEdge = GetEdge();
} while (MEdge != NIL);
if (AEList.top->next != AEList.bottom) {
panic("Unterminated upperward edge at closing");
}
exit(0);
}
/* read an edge from standard input. The reason for
the recopying of the edge is that, for space reasons,
the output format for edges is different from the internal
one
*/
static AEL_EDGEPTR GetEdge()
{
static EDGE redge;
int status;
if ( fread((char *)&redge, sizeof(EDGE), 1, stdin)
== 0 ) {
return(NIL);
}
medge.x = redge.x;
medge.xend = redge.xend;
medge.y = redge.y;
medge.sense = redge.sense;
return(&medge);
}
#ifdef DEBUG
BDump()
{
AEL_EDGEPTR edge = AEList.top;
while (edge != NIL) {
PrintEdge(edge);
edge = edge->next;
}
}
#endif
/*
Emit a box in left, bottom, right, top format
*/
static EmitBox(BottomEdge,TopY)
AEL_EDGEPTR BottomEdge;
int TopY;
{
OUT_BOX box;
box.xmax = BottomEdge->xend;
box.xmin = BottomEdge->x;
box.ymax = TopY;
box.ymin = BottomEdge->y;
if (box.ymax == box.ymin) {
#ifdef DEBUG
fprintf(stderr,"Zero box , %d at %d,%d\n",box.xmax - box.xmin,
box.xmin,box.ymin);
#endif
return;
}
#ifdef DEBUG
fprintf(stderr,"Boxer : Box from %d,%d to %d,%d\n",box.xmin,
box.ymin, box.xmax, box.ymax);
#endif
if ( fwrite(&box, sizeof(box), 1, stdout) == 0 ) {
panic("Bad write in EmitBox");
}
}
/*
Figure out the change in the geometry induced by the edge.
sense == UP means the interior is on high-Y side of the edge.
x is the x coordinate of the left side of the edge, xend is
the x coordinate of the right side of the edge. (i.e x < xend)
*/
edge_desc edge_type(M)
AEL_EDGEPTR M;
{
if ( M->sense == UP ) {
if ( M->x > AEdge->xend ) {
if (M->xend < AEdge->next->x) {
return (BEGIN);
} else if ( M->xend == AEdge->next->x ) {
return (LEFT_GROW);
} else {
return (BAD_EDGE);
}
} else if ( M->x == AEdge->xend ) {
if ( M->xend < AEdge->next->x ) {
return (RIGHT_GROW);
} else if ( M->xend == AEdge->next->x) {
return (JOIN);
} else {
return (BAD_EDGE);
}
} else {
return (BAD_EDGE);
}
} else if (M->sense == DOWN) {
if ( M->x == AEdge->x ) {
if ( M->xend == AEdge->xend ) {
return (END);
} else if ( M->xend < AEdge->xend ) {
return (LEFT_SHRINK);
} else {
return (BAD_EDGE);
}
} else if ( M->xend == AEdge->xend ) {
if ( M->x > AEdge->x ) {
return (RIGHT_SHRINK);
} else {
return (BAD_EDGE);
}
} else if ( M->x > AEdge->x && M->xend < AEdge->xend ) {
return (SPLIT);
} else {
return (BAD_EDGE);
}
} else {
return (BAD_EDGE);
}
}