typedef struct {
float x1, y1, x2, y2;
} line_segment_type;

/* Defined elsewhere (for example, VPFPTPLY.C */
int intersect( line_segment_type l1, line_segment_type l2,
float *xint, float *yint );

edge_rec_type create_edge_rec( row_type row, vpf_table_type edge_table );

/* Determine if a line segment intersects a box. */
/* If so return the intersection coordinate in the parameter list. */

static int box_intersection( line_segment_type lseg,
extent_type extent,
coordinate_type *coord )
{
line_segment_type boxseg;
float xint, yint;

boxseg.x1 = extent.x1;
boxseg.y1 = extent.y1;
boxseg.x2 = extent.x2;
boxseg.y2 = extent.y1;

if (intersect(lseg,boxseg,&xint,&yint)) {
coord->x = xint;
coord->y = yint;
return TRUE;
}

boxseg.x1 = extent.x2;
boxseg.y1 = extent.y1;
boxseg.x2 = extent.x2;
boxseg.y2 = extent.y2;

if (intersect(lseg,boxseg,&xint,&yint)) {
coord->x = xint;
coord->y = yint;
return TRUE;
}

boxseg.x1 = extent.x2;
boxseg.y1 = extent.y2;
boxseg.x2 = extent.x1;
boxseg.y2 = extent.y2;

if (intersect(lseg,boxseg,&xint,&yint)) {
coord->x = xint;
coord->y = yint;
return TRUE;
}

boxseg.x1 = extent.x1;
boxseg.y1 = extent.y2;
boxseg.x2 = extent.x1;
boxseg.y2 = extent.y1;

if (intersect(lseg,boxseg,&xint,&yint)) {
coord->x = xint;
coord->y = yint;
return TRUE;
}

return FALSE;

}

 

 

/* Replace the given coordinate string into the given edge row */

/* and write the new row to the specified edge table. */

static void write_edge_record( long int id, coordinate_type *coord,

long int ncoord, row_type row,

vpf_table_type *table )

{

int ID_, COORD_;

 

 

ID_ = table_pos("ID",*table);

COORD_ = table_pos("COORDINATES",*table);

 

 

put_table_element(ID_, row, *table, &id, 1);

put_table_element(COORD_, row, *table, coord, ncoord);

write_next_row(row,table);

 

 

}

 

 

 

 

 

 

#define WITHIN(x,y,ext) ((x>=ext.x1)&&(x<=ext.x2)&& \

(y>=ext.y1)&&(y<=ext.y2))

 

 

/*************************************************************************

*

*N vpf_edge_clip

*

*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

*

* Purpose:

*P

* This function clips an edge table to the given extent and writes

* the clipped table to the specified output path.

* NOTE: If a segment of an edge in the EDG table has both a beginning

* point and ending point outside of the given extent, and the line

* segment passes through the extent, the segment will not be written

* out to the new edge table.

*E

*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

*

* Parameters:

*A

* covpath <input> == (char *) path to the coverage of the edge table.

* extent <input> == (extent_type) clipping extent.

* outpath <input> == (char *) output path for the clipped edge table.

*E

*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

*

* History:

*H

* Barry Michaels Dec 1991 Original Version DOS Turbo C

*E

*************************************************************************/

void vpf_edge_clip( char *covpath, extent_type extent, char *outpath )

{

vpf_table_type in, out;

row_type row;

edge_rec_type inedge, outedge;

long int i,j,n,id;

line_segment_type lseg;

coordinate_type coord;

char path[255], *def;

float xmin, xmax, ymin, ymax;

 

 

/* Standardize extent, Lower Left, Upper Right */

xmin = (float)min(extent.x1,extent.x2);

xmax = (float)max(extent.x1,extent.x2);

ymin = (float)min(extent.y1,extent.y2);

ymax = (float)max(extent.y1,extent.y2);

extent.x1 = xmin;

extent.y1 = ymin;

extent.x2 = xmax;

extent.y2 = ymax;

 

 

sprintf(path,"%sedg",covpath);

in = vpf_open_table(path,disk,"rb",NULL);

 

 

rewind(in.fp);

fread(&n,sizeof(n),1,in.fp);

def = (char *)vpfmalloc((n+1)*sizeof(char));

fread(def,sizeof(char),n,in.fp);

def[n] = '\0';

sprintf(path,"%sedg",outpath);

out = vpf_open_table(path,disk,"wb",def);

 

 

for (i=1,id=1;i<=in.nrows;i++) {

row = get_row( i, in );

inedge = create_edge_rec( row, in );

if (!inedge.coord) {

free_row(row,in);

continue;

}

outedge.coord = (coordinate_type *)malloc(inedge.npts*sizeof(

coordinate_type));

if (!outedge.coord) {

free(inedge.coord);

free_row(row,in);

continue;

}

 

 

n = 0;

 

 

for (j=0;j<inedge.npts;j++) {

 

 

if (WITHIN(inedge.coord[j].x,inedge.coord[j].y,extent)) {

/* Current coordinate within extent */

 

 

if (j > 0) {

if (!WITHIN(inedge.coord[j-1].x,inedge.coord[j-1].y,

extent)) {

/* Previous coordinate was not in the extent - */

/* create an intersection vertex */

 

 

lseg.x1 = inedge.coord[j-1].x;

lseg.y1 = inedge.coord[j-1].y;

lseg.x2 = inedge.coord[j].x;

lseg.y2 = inedge.coord[j].y;

if (box_intersection(lseg,extent,&coord)) {

outedge.coord[n].x = coord.x;

outedge.coord[n].y = coord.y;

} else {

outedge.coord[n].x = lseg.x1;

outedge.coord[n].y = lseg.y1;

}

n++;

}

}

outedge.coord[n].x = inedge.coord[j].x;

outedge.coord[n].y = inedge.coord[j].y;

n++;

} else {

if (j > 0) {

if (WITHIN(inedge.coord[j-1].x,inedge.coord[j-1].y,extent)) {

 

 

/* The coordinate is not within the extent and */

/* the previous one was - Create an intersection */

/* vertex point and write the current edge record. */

 

 

lseg.x1 = inedge.coord[j-1].x;

lseg.y1 = inedge.coord[j-1].y;

lseg.x2 = inedge.coord[j].x;

lseg.y2 = inedge.coord[j].y;

if (box_intersection(lseg,extent,&coord)) {

outedge.coord[n].x = coord.x;

outedge.coord[n].y = coord.y;

} else {

outedge.coord[n].x = lseg.x2;

outedge.coord[n].y = lseg.y2;

}

 

 

/* Break the edge in (at least) two */

n++;

write_edge_record( id, outedge.coord, n, row, &out );

id++;

n=0;

 

 

}

}

}

}

free(inedge.coord);

 

 

if (n > 0) {

write_edge_record( id, outedge.coord, n, row, &out );

id++;

}

 

 

free(outedge.coord);

free_row(row,in);

}

 

 

vpf_close_table(&in);

vpf_close_table(&out);

}