home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
vis-ftp.cs.umass.edu
/
vis-ftp.cs.umass.edu.tar
/
vis-ftp.cs.umass.edu
/
pub
/
Software
/
ASCENDER
/
ascendMar8.tar
/
UMass
/
BoldtOld
/
MERGE
/
mergelines.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-22
|
12KB
|
481 lines
#include "geometry2d.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
typedef enum flag_type {ON, OFF} FLAG;
typedef struct NODE {
POINT2D *endpt1, *endpt2;
float contrast;
LINE2D *lineABC;
FLAG flag;
struct NODE *next;} *LINELIST;
typedef struct {
int rowcells;
int colcells;
int blockdim;
int startx;
int starty;
LINELIST *cells;} LINEGRID;
#define GRIDCELL(grid,x,y) \
(((grid)->cells)+(y)*((grid)->colcells)+(x))
#define CREATE_NODE(node) \
{node = (struct NODE *)malloc(sizeof(struct NODE)); \
node->endpt1 = (POINT2D *)malloc(sizeof(POINT2D)); \
node->endpt2 = (POINT2D *)malloc(sizeof(POINT2D)); \
node->lineABC = (LINE2D *)malloc(sizeof(LINE2D));}
#define FREE_NODE(node) \
{free(node->endpt1); \
free(node->endpt2); \
free(node->lineABC); \
free(node);}
/**********************************************************************/
LINELIST read_in_lines(char *filename, float startX, float startY)
{
FILE *infile;
float x1,y1,x2,y2,contrast;
LINELIST head, current, node;
if ((infile = fopen(filename,"r")) == NULL) {
perror("error opening input file");
perror(filename);
return(NULL);
}
CREATE_NODE(current);
current->flag = OFF;
current->next = NULL;
head = current;
while ((fscanf(infile,"%f %f %f %f %f",&x1,&y1,&x2,&y2,&contrast)) != EOF) {
CREATE_NODE(node);
set_point2d(node->endpt1,(startX + x1),(startY + y1));
set_point2d(node->endpt2,(startX + x2),(startY + y2));
node->contrast = contrast;
set_line2d_from_endpoints(node->lineABC,node->endpt1,node->endpt2);
node->flag = ON;
node->next = NULL;
current->next = node;
current = node;
}
if (fclose(infile) == EOF) {
perror("error closing input file");
perror(filename);
}
return(head);
}
void write_out_file_header(char *filename)
{
FILE *outfile;
if ((outfile = fopen(filename,"w")) == NULL) {
perror("error opening output file");
perror(filename);
return;
}
fprintf(outfile,"3D: NO\n");
fprintf(outfile,"DATA:\n");
if (fclose(outfile) == EOF) {
perror("error closing output file");
perror(filename);
}
return;
}
LINELIST write_out_lines(LINELIST linelist, char *filename, char *mode)
{
FILE *outfile;
LINELIST current;
if ((outfile = fopen(filename,mode)) == NULL) {
perror("error opening output file");
perror(filename);
return(linelist);
}
current = linelist;
while (current != NULL) {
if (current->flag == ON)
if (fprintf(outfile,"%.2f %.2f %.2f %.2f %.2f\n",
current->endpt1->x, current->endpt1->y,
current->endpt2->x, current->endpt2->y,
current->contrast) == EOF) {
perror("error writing to output file");
perror(filename);
return(linelist);
}
current = current->next;
}
if (fclose(outfile) == EOF) {
perror("error closing output file");
perror(filename);
}
return(linelist);
}
int count_lines(LINELIST linelist)
{
int count;
LINELIST current;
if (linelist == NULL)
return(0);
count = 0;
current = linelist;
while (current != NULL) {
if (current->flag == ON)
count++;
current = current->next;
}
return(count);
}
void free_lines(LINELIST linelist)
{
LINELIST current, nextptr;
current = linelist;
while (current != NULL) {
nextptr = current->next;
FREE_NODE(current);
current = nextptr;
}
return;
}
/**********************************************************************/
/* maximum absolute sine of angle between lines to merge */
/* #define SIN_ANGLE_THRESHOLD 0.01745241 */ /* 1 degree */
#define SIN_ANGLE_THRESHOLD 0.034906585 /* 2 degrees */
/* maximum lateral distance in pixels between lines */
#define LATERAL_DISTANCE_THRESHOLD 1.0
/* maximum longitudinal distance in pixels between lines */
#define GAP_THRESHOLD 1.0
/* Reorder 4 nearly colinear points p1,...,p4 and return them as pa,...,pd */
/* so that pa and pd are at the two extremes and pb and pc are in the middle.*/
void rearrange_endpoints(POINT2D *p1, POINT2D *p2, POINT2D *p3, POINT2D *p4,
POINT2D *pa, POINT2D *pb, POINT2D *pc, POINT2D *pd)
{
POINT2D pmid;
LINE2D uvec;
pmid.x = (p1->x + p2->x + p3->x + p4->x) / 4.0;
pmid.y = (p1->y + p2->y + p3->y + p4->y) / 4.0;
set_line2d(&uvec, p1->x - pmid.x, p1->y - pmid.y, 0.0);
if (signed_distance_pl2d(p1,&uvec) > signed_distance_pl2d(p2,&uvec)) {
copy_point2d(pa,p1);
copy_point2d(pb,p2);}
else {
copy_point2d(pa,p2);
copy_point2d(pb,p1);}
if (signed_distance_pl2d(p3,&uvec) > signed_distance_pl2d(p4,&uvec)) {
copy_point2d(pc,p3);
copy_point2d(pd,p4);}
else {
copy_point2d(pc,p4);
copy_point2d(pd,p3);}
if (signed_distance_pl2d(pc,&uvec) > signed_distance_pl2d(pa,&uvec))
swap_points2d(pa,pc);
if (signed_distance_pl2d(pd,&uvec) > signed_distance_pl2d(pb,&uvec))
swap_points2d(pb,pd);
return;
}
/* Determine whether line1 and line2 should be merged. If so, modify */
/* line1 to be the merged line and delete line2. */
void process_line_pair (struct NODE *line1, struct NODE *line2)
{
POINT2D pta,ptb,ptc,ptd;
LINE2D mergeABC;
/*
printf("L1 = %.2f %.2f %.2f %.2f \nL2 = %.2f %.2f %.2f %.2f\n",
line1->endpt1->x,line1->endpt1->y,
line1->endpt2->x,line1->endpt2->y,
line2->endpt1->x,line2->endpt1->y,
line2->endpt2->x,line2->endpt2->y);
printf("sin angle is %f\n", sin_angle_ll2d(line1->lineABC,line2->lineABC));
*/
if (sin_angle_ll2d(line1->lineABC,line2->lineABC) < SIN_ANGLE_THRESHOLD) {
rearrange_endpoints(line1->endpt1,line1->endpt2,
line2->endpt1,line2->endpt2,
&pta,&ptb,&ptc,&ptd);
set_line2d_from_endpoints(&mergeABC,&pta,&ptd);
/*
printf("%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n",
line1->endpt1->x,line1->endpt1->y,
line1->endpt2->x,line1->endpt2->y,
line2->endpt1->x,line2->endpt1->y,
line2->endpt2->x,line2->endpt2->y);
printf("%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n",
pta.x,pta.y,ptb.x,ptb.y,ptc.x,ptc.y,ptd.x,ptd.y);
printf("L1 = %f %f %f\n",line1->lineABC->a, line1->lineABC->b,
line1->lineABC->c);
printf("L2 = %f %f %f\n",line2->lineABC->a, line2->lineABC->b,
line2->lineABC->c);
printf("ABC = %f %f %f\n",mergeABC.a,mergeABC.b,mergeABC.c);
printf("%f < %f\n",
(sin_angle_ll2d(&mergeABC,line1->lineABC)),SIN_ANGLE_THRESHOLD);
printf("%f < %f\n",
(sin_angle_ll2d(&mergeABC,line2->lineABC)),SIN_ANGLE_THRESHOLD);
printf("%f < %f\n",
distance_pl2d(&ptb,&mergeABC),LATERAL_DISTANCE_THRESHOLD);
printf("%f < %f\n",
(distance_pl2d(&ptc,&mergeABC)),LATERAL_DISTANCE_THRESHOLD);
printf("%f < %f\n",(distance_pp2d(&pta,&ptd)),
(distance_pp2d(line1->endpt1,line1->endpt2) +
distance_pp2d(line2->endpt1,line2->endpt2) +
GAP_THRESHOLD));
*/
if ((sin_angle_ll2d(&mergeABC,line1->lineABC) < SIN_ANGLE_THRESHOLD) &&
(sin_angle_ll2d(&mergeABC,line2->lineABC) < SIN_ANGLE_THRESHOLD) &&
(distance_pl2d(&ptb,&mergeABC) < LATERAL_DISTANCE_THRESHOLD) &&
(distance_pl2d(&ptc,&mergeABC) < LATERAL_DISTANCE_THRESHOLD) &&
(distance_pp2d(&pta,&ptd) <=
(distance_pp2d(line1->endpt1,line1->endpt2) +
distance_pp2d(line2->endpt1,line2->endpt2) +
GAP_THRESHOLD)))
/* merge lines */
{
/*
printf("newpath %.2f %.2f mt %.2f %.2f lt 1 0 0 setrgbcolor stroke\n",
line1->endpt1->x,line1->endpt1->y,
line1->endpt2->x,line1->endpt2->y);
printf("newpath %.2f %.2f mt %.2f %.2f lt 0 1 0 setrgbcolor stroke\n",
line2->endpt1->x,line2->endpt1->y,
line2->endpt2->x,line2->endpt2->y);
*/
/*
printf("newpath %.2f %.2f mt %.2f %.2f lt 0 0 1 setrgbcolor stroke\n",
pta.x,pta.y,ptd.x,ptd.y);
*/
copy_point2d(line1->endpt1,&pta);
copy_point2d(line1->endpt2,&ptd);
copy_line2d(line1->lineABC,&mergeABC);
line1->contrast = (line1->contrast + line2->contrast) / 2.0;
line2->flag = OFF;
}
}
}
void process_line_lists(LINELIST list1, LINELIST list2)
{
LINELIST listptr;
while (list1 != NULL) {
if (list1->flag == ON) {
listptr = list2;
while (listptr != NULL) {
if (listptr->flag == ON)
process_line_pair(list1,listptr);
listptr = listptr->next;
}
}
list1 = list1->next;
}
}
/**********************************************************************/
void parse_filename (char *namestring, int *x, int *y)
{
char *ptr1, *ptr2;
ptr1 = namestring;
while(*ptr1++ != NULL);
while(*(--ptr1) != '.');
ptr2 = ptr1;
while(*(--ptr2) != 'Y');
*ptr1 = '\0';
*y = atoi(ptr2+1);
*ptr1 = '.';
ptr1 = ptr2;
while(*(--ptr1) != 'X');
*ptr2 = '\0';
*x = atoi(ptr1+1);
*ptr2 = 'Y';
return;
}
int read_info(char *info_filename, char *infolabel)
{
FILE *infile;
char *strptr;
char infoline[64];
int info;
if ((infile = fopen(info_filename,"r")) == NULL) {
perror("error opening info file");
perror(info_filename);
return(-1);
}
strptr = infolabel;
while(fgets(infoline, 63, infile) != NULL)
if (!strncmp(infoline,infolabel,strlen(infolabel)-1)) {
sscanf((infoline+strlen(infolabel)+1),"%d",&info);
fclose(infile);
return(info);
}
perror("requested info not found in info file");
perror(infolabel);
fclose(infile);
return(-1);
}
LINEGRID *init_line_grid(char *info_filename)
{
LINEGRID *grid;
int rowblocks, colblocks;
int width, overlap;
int imrowmax, croprowmax, cropcolmin;
imrowmax = read_info(info_filename,"image maxrow");
croprowmax = read_info(info_filename,"crop maxrow");
cropcolmin = read_info(info_filename,"crop mincol");
rowblocks = read_info(info_filename,"row numblocks");
colblocks = read_info(info_filename,"col numblocks");
width = read_info(info_filename,"block width");
overlap = read_info(info_filename,"block overlap");
grid = (LINEGRID *)malloc(sizeof(LINEGRID));
grid->rowcells = rowblocks;
grid->colcells = colblocks;
grid->blockdim = width - overlap;
grid->startx = cropcolmin;
grid->starty = imrowmax - croprowmax;
grid->cells = (LINELIST *)malloc(rowblocks*colblocks*(sizeof(LINELIST)));
return(grid);
}
void read_line_file_into_grid(char *filename, LINEGRID *grid)
{
LINELIST linelist;
int startX, startY;
int xindex, yindex;
parse_filename(filename,&startX,&startY);
linelist = read_in_lines(filename,(float)startX,(float)startY);
xindex = (int)((startX - grid->startx) / grid->blockdim);
yindex = (int)((startY - grid->starty) / grid->blockdim);
*GRIDCELL(grid,xindex,yindex) = linelist;
return;
}
/**********************************************************************/
#define INFOFILE argv[1]
#define OUTPUTFILE argv[2]
void main(int argc, char *argv[])
{
LINEGRID *grid;
int count = 3;
int row, col, numcells;
grid = init_line_grid(INFOFILE);
while(count<argc) {
read_line_file_into_grid(argv[count], grid);
count++;}
printf("\nGrid counts\n");
for (row = 0; row < grid->rowcells; row++) {
printf(" ");
for (col = 0; col < grid->colcells; col++)
printf(" %d",
count_lines(*GRIDCELL(grid,col,(grid->rowcells - 1 - row))));
printf("\n");
}
printf("\n");
/* merging across columns */
for (row = 0; row < grid->rowcells; row++)
for (col = 0; col < grid->colcells - 1; col++) {
process_line_lists(*GRIDCELL(grid,col,row),*GRIDCELL(grid,col+1,row));
}
/* merging down rows */
for (col = 0; col < grid->colcells; col++)
for (row = 0; row < grid->rowcells - 1; row++) {
process_line_lists(*GRIDCELL(grid,col,row),*GRIDCELL(grid,col,row+1));
}
/* output to file */
numcells = grid->rowcells * grid->colcells;
count = 0;
write_out_file_header(OUTPUTFILE);
while (count < numcells) {
write_out_lines((grid->cells)[count],OUTPUTFILE,"a");
free_lines((grid->cells)[count]);
count++;
}
return;
}