home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
gdead.berkeley.edu
/
gdead.berkeley.edu.tar
/
gdead.berkeley.edu
/
pub
/
cad-tools
/
ciftomann.tar
/
edger_dir
/
edge_polygon.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-01-28
|
7KB
|
321 lines
#include "ciftomann.h"
#include "intersection.h"
#include "aeledge.h"
#include <stdio.h>
#include "fd.h"
static AEL_LIST AEList;
static AEL_EDGE medge;
static AEL_EDGEPTR AEdge;
static int CurrentY;
extern FILE *out_desc;
AEL_EDGEPTR MakeEdge();
static AEL_EDGEPTR GetEdge();
/*
* Convert an arbitrary Manhatten polygon into edges.
* A scan_line algorithm is used in a process almost
* identical to the merging process. See the code for
* merge for further comments.
* Self-intersecting polygons are handled
* properly through comparison of the relative sense
* of any edge and the first edge encountered (which
* must be an exterior edge) and keeping a running total
* of the depth of overlap on the scan-line at all times.
*/
edge_polygon()
{
AEL_EDGEPTR MEdge,
Position;
AEList.bottom = MakeEdge(INFINITY,INFINITY,-INFINITY,1,NIL,NIL);
AEList.top = MakeEdge(-INFINITY,-INFINITY,-INFINITY,1,NIL,NIL);
AEList.top->next = AEList.bottom;
AEList.bottom->last = AEList.top;
MEdge = GetEdge();
ProgName = "FixPolygon";
do {
CurrentY = MEdge->y;
AEdge = AEList.top;
do {
/* find the proper location on the scanline */
while ( Greater_than_Equal(MEdge->x, AEdge->next->x) )
AEdge = AEdge->next;
Position = AEdge->last;
do {
Update(MEdge);
AEdge = AEdge->next;
} while (MEdge->sense != 0);
MEdge = GetEdge();
if (Position != NIL)
AEdge = Position;
else
AEdge = AEList.top;
} while (MEdge != NIL && MEdge->y == CurrentY);
ClearEmit();
} while (MEdge != NIL);
if (AEList.top->next != AEList.bottom)
panic("Unterminated upward edges at end of merge");
}
static Update(M)
AEL_EDGEPTR M;
{
switch (Intersection(AEdge,M)) {
case COINCIDENT : /* M---------M
C---------C */
AEdge->sense += M->sense;
M->sense = 0;
if (AEdge->sense == 0) {
AEdge = AEdge->last;
EmitEdge(AEdge->next,DOWN);
Remove(AEList,AEdge->next);
}
break;
case A_LCOVERS_M : /* M---------M
C------------C */
AEdge->x = M->xend;
InsertAbove(AEdge,M->x,M->xend,CurrentY,AEdge->sense + M->sense);
M->sense = 0;
if (AEdge->last->sense == 0) {
EmitEdge(AEdge->last,DOWN);
Remove(AEList,AEdge->last);
}
break;
case M_LCOVERS_A : /* M------------M
C---------C */
M->x = AEdge->xend;
AEdge->sense += M->sense;
if (AEdge->sense == 0) {
AEdge = AEdge->last;
EmitEdge(AEdge->next,DOWN);
Remove(AEList,AEdge->next);
}
break;
case LDISJOINT : /* M------M
C----C */
case LPOINT : /* M------M
C-----C */
InsertAbove(AEdge,M->x,M->xend,CurrentY,M->sense);
EmitEdge(AEdge->last,UP);
M->sense = 0;
break;
case M_RCOVERS_A : /* M------------M
C-------C */
InsertAbove(AEdge,M->x,AEdge->x,CurrentY,M->sense);
EmitEdge(AEdge->last,UP);
AEdge->sense += M->sense;
M->sense = 0;
if (AEdge->sense == 0) {
AEdge = AEdge->last;
EmitEdge(AEdge->next,DOWN);
Remove(AEList,AEdge->next);
}
break;
case LOVERLAP : /* M-------M
C------C */
InsertAbove(AEdge,M->x,AEdge->x,CurrentY,M->sense);
EmitEdge(AEdge->last,UP);
InsertAbove(AEdge,AEdge->x,M->xend,CurrentY,AEdge->sense + M->sense);
M->sense = 0;
AEdge->x = M->xend;
if (AEdge->last->sense == 0) {
EmitEdge(AEdge->last,DOWN);
Remove(AEList,AEdge->last);
}
break;
case M_COVERS_A : /* M------------M
C--------C */
InsertAbove(AEdge,M->x,AEdge->x,CurrentY,M->sense);
EmitEdge(AEdge->last,UP);
AEdge->sense += M->sense;
M->x = AEdge->xend;
if (AEdge->sense == 0) {
AEdge = AEdge->last;
EmitEdge(AEdge->next,DOWN);
Remove(AEList,AEdge->next);
}
break;
case RDISJOINT : /* M-----M
C-----C */
case RPOINT : /* M-----M
C------C */
break;
case A_RCOVERS_M : /* M-----M
C------------C */
InsertAbove(AEdge,AEdge->x,M->x,CurrentY,AEdge->sense);
AEdge->x = M->x;
AEdge->sense += M->sense;
M->sense = 0;
if (AEdge->sense == 0) {
AEdge = AEdge->last;
EmitEdge(AEdge->next,DOWN);
Remove(AEList,AEdge->next);
}
break;
case A_COVERS_M : /* M--------M
C------------C */
InsertAbove(AEdge,AEdge->x,M->x,CurrentY,AEdge->sense);
InsertAbove(AEdge,M->x,M->xend,CurrentY,AEdge->sense + M->sense);
AEdge->x = M->xend;
M->sense = 0;
if (AEdge->last->sense == 0) {
EmitEdge(AEdge->last,DOWN);
Remove(AEList,AEdge->last);
}
break;
case ROVERLAP : /* M------M
C-------C */
InsertAbove(AEdge,AEdge->x,M->x,CurrentY,AEdge->sense);
AEdge->x = M->x;
AEdge->sense += M->sense;
M->x = AEdge->xend;
if (AEdge->sense == 0) {
AEdge = AEdge->last;
EmitEdge(AEdge->next,DOWN);
Remove(AEList,AEdge->next);
}
break;
}
}
extern EDGE EdgeArray[];
extern int NumEdges;
extern int ArrayIndex;
static AEL_EDGEPTR GetEdge()
{
if (ArrayIndex < NumEdges) {
medge.x = EdgeArray[ArrayIndex].x;
medge.xend = EdgeArray[ArrayIndex].xend;
medge.sense = EdgeArray[ArrayIndex].sense;
medge.y = EdgeArray[ArrayIndex].y;
ArrayIndex++;
return(&medge);
} else
return(NIL);
}
#define SAVE(edge) { redge.x = edge->x;\
redge.xend = edge->xend;\
redge.sense = sense;\
redge.y = CurrentY;\
Empty = 0; }
static int Empty = 1;
static EDGE redge;
static EmitEdge(edge,sense)
AEL_EDGEPTR edge;
int sense;
{
if (Empty)
SAVE(edge)
else {
if (redge.sense == sense && redge.xend == edge->x)
redge.xend = edge->xend;
else if (redge.sense == -sense && redge.xend == edge->xend)
if (redge.x == edge->x)
Empty = 1;
else
redge.xend = edge->x;
else {
#ifdef DEBUG
fprintf(stderr,"Fix Emits %d->%d at %d : sense = %d\n",redge.x,
redge.xend,redge.y,redge.sense);
#endif
if ( fwrite((char *)&redge, sizeof(EDGE), 1, out_desc) == 0 )
panic("Bad write in EmitEdge");
SAVE(edge);
}
}
}
static ClearEmit()
{
if (!Empty) {
#ifdef DEBUG
fprintf(stderr,"Fix Emits %d->%d at %d : sense = %d\n",redge.x,
redge.xend,redge.y,redge.sense);
#endif
if ( fwrite((char *)&redge, sizeof(EDGE), 1, out_desc) == 0 )
panic("Bad write in EmitEdge");
Empty = 1;
}
}
#ifdef DEBUG
FDump()
{
AEL_EDGEPTR edge = AEList.top;
while (edge != NIL) {
PrintEdge(edge);
edge = edge->next;
}
}
#endif