home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Current Shareware 1994 January
/
SHAR194.ISO
/
graphuti
/
polyops.zip
/
POLY_IN.C
< prev
next >
Wrap
Text File
|
1991-08-27
|
23KB
|
757 lines
/* Input routines for polyops.c */
#include <stdio.h>
#include <graphics.h>
#include <ctype.h>
#include <alloc.h>
#include <math.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include <stdarg.h>
#define MAXPTS 100 /* maximum size of ANY polygon used, not just input */
#define MAXX 640 /* greater than any permissible x-coordinate */
#define MAXCOMPS 20 /* maximum number of output polygons allowed */
#define MAXCHOICE 12 /* menu choices */
#define ESC 27
#define PLUS 43
#define MINUS 45
#define INS -82
#define DEL -83
#define UP -72
#define DN -80
#define LEFT -75
#define RIGHT -77
#define HOME -71
#define END -79
#define PGUP -73
#define PGDN -81
#define SHFT_HOME 55
#define MIN(a,b) (a) < (b) ? (a) : (b)
#define MAX(a,b) (a) > (b) ? (a) : (b)
#define CLIP(x,a,b) MIN(MAX((x),(a)),(b)) /* assumes a <= b */
typedef struct {double x; double y;} point;
typedef struct {point first; point second;} segment;
typedef struct {int nverts; double x[MAXPTS]; double y[MAXPTS];} polygon;
typedef struct {point v; int class; int next;} ventry; /* for vertex rings */
typedef struct {point p1; point p2; int del;} fentry; /* for frags list */
/* function prototypes */
void
check(int),
clrmark(void),
clearline(int,int),
display(void),
gprintf(int, int, int, char *,...),
initialize(void),
mark(void),
move_to(int,int),
msgcursor(void),
msgotoxy(int,int),
mshbounds(int,int),
mshidecur(void),
msmotion(int *,int *),
mspage(int),
msshowcur(void),
msstatus(int *,int *,int *),
msvbounds(int,int),
pause(void);
int
getint(int,char *),
get_poly(void),
load_data(char *),
msinit(void),
msrelease(int),
prompt(int,int,int,char *msg),
sx(double),
sy(double);
double
wx(int),
wy(int);
extern int
getdouble(int,char *),
getkey(void);
extern int normcolr;
extern double vd[];
int vi[10];
/* variables and constants for graphics interface --------------------- */
int xc,yc; /* coordinates of CP */
int delta = 10; /* initial increment for moving CP */
int colr; /* graph color */
int colr1 = 0; /* background color for message line */
int colr2 = 14; /* text color for prompts */
int colr3 = 10; /* text color for display of coordinates */
int bkcolor = 0; /* general background color, for erasures */
int np; /* number of points currently marked */
int mx[MAXPTS], my[MAXPTS]; /* coordinates of marked points */
void *block1, *block2; /* marked point indicators */
void *cross; /* CP indicator */
int x0=10,y0=329; /* home pos for cursor */
int xdec=1, ydec=1; /* precision values for display of CP */
int sxmax,symax; /* maximum/minimum screen coordinates */
int xb,yb; /* for graphics prompts */
int graphics_init; /* flag for graphics initialization */
double xscale,yscale,xscale1,yscale1; /* scaling constants */
int mouse; /* mouse driver loaded flag */
int stat; /* mouse button status */
/* ----------------------------------------------------------------------- */
int mode; /* graphics mode used */
extern polygon A,B; /* input polygons */
extern int oper; /* intersection, union, A-B, B-A */
char filename[32], fname[13];
int ax1[MAXPTS],ay1[MAXPTS]; /* screen vertices of A */
int ax2[MAXPTS],ay2[MAXPTS]; /* screen vertices of B */
int nv1,nv2; /* sizes of A and B */
int xx=32,yy=192; /* query location, menu */
/* ----------------- graphics entry of polygons -------------------------- */
/* Fills the global integer arrays ax1[],ay1[],ax2[],ay2[] with the screen
coordinates of the vertices of two polygons entered by the user. The
integers nv1,nv2 are set to the sizes of the polygons. */
int
graf_in(void)
{
int i;
for (i=0; i<12; i++) fname[i] = ' '; /* be sure display name is empty */
fname[12] = '\0';
enter_polys:
setviewport(0,0,sxmax,yb-1,1);
clearviewport();
setviewport(0,0,sxmax,symax,1);
xc=x0; yc=y0;
moveto(xc,yc);
if (mouse)
msgotoxy(xc,yc);
putimage(xc-5,yc-5,cross,XOR_PUT);
prompt(xb,yb+3,1,"Mark vertices of first polygon, press Enter when done");
display(); /* show values of cx,cy */
colr = 10; /* draw A in green */
i = get_poly(); /* get user input for first polygon */
if (i==-1) /* Esc pressed during poly input */
{
np=0;
cleardevice();
return 0;
}
if (np<3)
{
prompt(xb,yb+3,1,
"At least 3 vertices must be marked. Press any key to reenter");
if (getch() == 27)
{
np=0;
cleardevice();
return 0;
}
else
goto enter_polys;
}
nv1 = np;
for (i=0; i<nv1; i++)
{
ax1[i] = mx[i];
ay1[i] = my[i];
}
np = 0;
prompt(xb,yb+3,1,"Mark vertices of second polygon, press Enter when done");
colr = 12; /* draw B in red */
i = get_poly(); /* get user input for next polygon */
if (i==-1) /* Esc pressed during poly input */
{
cleardevice();
return 0;
}
if (np<3)
{
prompt(xb,yb+3,1,
"At least 3 vertices must be marked. Press any key to reenter");
if (getch() == 27)
{
cleardevice();
return 0;
}
goto enter_polys;
}
nv2 = np;
for (i=0; i<nv2; i++)
{
ax2[i] = mx[i];
ay2[i] = my[i];
}
np = 0;
prompt(xb,yb+3,1,"Press any key to continue");
getch();
cleardevice();
return 1;
}
/* ------------------------------------------------------------------------ */
/* accept user input of polygon from screen */
int
get_poly(void)
{
int i,j,c,xtmp=xc,ytmp=yc;
np = 0;
if (mouse) {
msinit(); /* clear mouse parameters */
msgotoxy(xc,yc);
}
while (1) {
if (kbhit()) {
c = getkey();
if (c == 13) /* Enter key exits */
goto gp_ret;
check(c); /* cursor movement, +/- */
if (c==INS) /* Ins marks (xc,yc) */
mark();
if (c==DEL) /* clear last mark */
clrmark();
if (c==27)
return -1; /* quit if Esc pressed */
}
if (mouse) {
msstatus(&stat,&xtmp,&ytmp);
if (stat == 2) /* right button exits */
goto gp_ret;
if (stat == 1) { /* left button marks point) */
mark(); /* mark current point */
while (stat == 1) /* wait for button release */
msstatus(&stat,&xtmp,&ytmp);
continue;
}
if (stat == 0) { /* no button pressed */
msmotion(&i,&j); /* check movement */
if (i || j) /* if mouse moved... */
move_to(xtmp,ytmp); /* ..update cursor and (xc,yc) */
}
}
}
gp_ret:
if (np) {
move_to(x0,y0); /* get cross hairs out of the way */
setcolor(colr); /* green for A, red for B */
line(mx[np-1],my[np-1],mx[0],my[0]); /* close up polygon */
}
setcolor(normcolr);
return np;
}
/* ----------------------- hand entry of polygons ------------------------ */
int
kb_in(void)
{
int i=0;
char s[256];
for (i=0; i<12; i++) fname[i] = ' '; /* be sure display name is empty */
fname[12] = '\0';
printf("Vertices must be in the range [0,1]\n");
vA:
printf("Enter number of vertices for polygon A : ");
gets(s);
if (strlen(s)==0 || *s == 27) return 0;
getint(1,s);
A.nverts = nv1 = vi[0];
if (A.nverts<3 || A.nverts>MAXPTS)
{
printf("Too many or not enough vertices. Please reenter.\n");
goto vA;
}
printf("Enter vertices of A :\n");
gets(s);
if (getdouble(2*A.nverts,s) != 2*A.nverts)
{
printf("Too many or not enough vertices. Please reenter.\n");
goto vA;
}
for (i=0; i<A.nverts; i++)
{
A.x[i] = vd[2*i];
ax1[i] = sx(A.x[i]);
A.y[i] = vd[2*i+1];
ay1[i] = sy(A.y[i]);
}
vB:
printf("Enter number of vertices for polygon B : ");
gets(s);
if (strlen(s)==0 || *s == 27) return 0;
getint(1,s);
B.nverts = nv2 = vi[0];
if (B.nverts<3 || B.nverts>MAXPTS)
{
printf("Too many or not enough vertices. Please reenter.\n");
goto vB;
}
printf("Enter vertices of B :\n");
gets(s);
if (getdouble(2*B.nverts,s) != 2*B.nverts)
{
printf("Too many or not enough vertices. Please reenter.\n");
goto vB;
}
for (i=0; i<B.nverts; i++)
{
B.x[i] = vd[2*i];
ax2[i] = sx(B.x[i]);
B.y[i] = vd[2*i+1];
ay2[i] = sy(B.y[i]);
}
return 1;
}
/* ---------- read polygons (and world coords) from disk file ----------- */
int
load_data(char *s)
{
FILE *fp;
int i,j,nv,v[2*MAXPTS];
int c;
char s1[20], *sp, *sp1;
double z;
if (strncmpi(s,"pdat",4)==0) /* file 'poly.dat' contains numerous */
{ /* subfiles named 'pdat1, pdat2,... */
fp = fopen("poly.dat","rt");
if (fp == NULL) /* if 'poly.dat' does not exist .. */
goto b; /* .. try to open stand alone file */
/* search "poly.dat" for requested filename */
while (!feof(fp))
{
sp=s1;
while(isalnum(c = getc(fp)))
{
*sp = c;
sp++;
}
*sp = '\0';
if (!strcmp(s1,s))
{
c = 'F'; /* to show filename found */
break;
}
while(!isalpha(c = getc(fp)) && c != -1)
;
if (c != -1)
ungetc(c,fp);
}
if (c != 'F')
{
fclose(fp);
goto b; /* not found in 'poly.dat' so try to open stand alone */
}
}
else /* not 'pdat*' file */
b:
if ((fp = fopen(s,"rt")) == NULL)
return 0;
strcpy(filename,s); /* save filename */
/* make 12-character display name */
sp = filename+strlen(filename);
sp1 = fname+12;
while(sp >= filename && *sp != '\\' && *sp != ':')
*sp1-- = *sp--;
while (sp1 >= fname) *sp1-- = ' '; /* pad left to 12 characters */
/* -------------- get data from file fp -------------- */
fscanf(fp,"%d",&nv1); /* number of vertices, polygon 1 */
A.nverts = nv1;
for (i=0; i<nv1; i++) {
fscanf(fp,"%lf",&z);
A.x[i] = z;
ax1[i] = sx(z); /* screen x-coordinates, A */
}
for (i=0; i<nv1; i++) {
fscanf(fp,"%lf",&z);
A.y[i] = z;
ay1[i] = sy(z); /* screen y-coordinates, A */
}
fscanf(fp,"%d",&nv2); /* similar data for B */
B.nverts = nv2;
for (i=0; i<nv2; i++) {
fscanf(fp,"%lf",&z);
B.x[i] = z;
ax2[i] = sx(z); /* screen x-coordinates, B */
}
for (i=0; i<nv2; i++) {
fscanf(fp,"%lf",&z);
B.y[i] = z;
ay2[i] = sy(z); /* screen y-coordinates, B */
}
fclose(fp);
return 1;
}
/* ======================================================================== */
/* miscellaneous supporting routines , listed alphabetically */
/* ======================================================================== */
/* ---- extract n integer values from string s, put them in array vi[] --- */
int
getint(int n, char *s)
{
int cnt=0;
char *p;
if (n == 0) return cnt;
p = s;
while (cnt < n && *p)
{
while (!isdigit(*p)) p++;
vi[cnt] = atoi(p);
while (isdigit(*p)) p++;
cnt++;
}
return cnt;
}
/* ==================== Graphics interface functions ==================== */
/* Functions necessary to make the interface work, listed alphabetically */
/* ---------------------------------------------------------------------- */
/* check user keystroke for arrow keys and +/- commands */
void
check(int c)
{
switch(c)
{
case PLUS: /* increase cursor increment */
delta = MIN(10*delta,100);
break;
case MINUS: /* decrease cursor increment */
delta = MAX(delta/10,1);
break;
case UP:
move_to(xc,yc-delta);
break;
case DN:
move_to(xc,yc+delta);
break;
case LEFT:
move_to(xc-delta,yc);
break;
case RIGHT:
move_to(xc+delta,yc);
break;
case HOME: /* diagonal UL */
move_to(xc-delta,yc-delta);
break;
case END: /* diagonal DL */
move_to(xc-delta,yc+delta);
break;
case PGUP: /* diagonal UR */
move_to(xc+delta,yc-delta);
break;
case PGDN: /* diagonal DR */
move_to(xc+delta,yc+delta);
break;
case SHFT_HOME: /* home position for cursor */
move_to(x0,y0);
break;
}
}
/* ---------------------------------------------------------------------- */
void
clearline(int x, int y)
{
bar(x,y,sxmax,y+8);
}
/* ---------------------------------------------------------------------- */
/* clear last mark made */
void
clrmark(void)
{
int i;
int x,y;
if (np==0)
return;
np--;
if(np)
{
putimage(xc-5,yc-5,cross,XOR_PUT);
setcolor(bkcolor);
line(mx[np-1],my[np-1],mx[np],my[np]); /* erase line from last mark */
setcolor(normcolr);
putimage(xc-5,yc-5,cross,XOR_PUT);
}
}
/* ---------------------------------------------------------------------- */
/* show coordinates of CP on screen */
/* the display is on line 24, starting at column 62 */
void
display(void)
{
bar(496,yb+1,sxmax-2,symax-1); /* clear display space */
gprintf(496,yb+3,colr3,"%.2f %.2f",wx(xc),wy(yc));
setcolor(15);
line(sxmax,yb,sxmax,symax);
}
/* ---------------------------------------------------------------------- */
/* graphics version of printf(); from Borland graphics demo BGIDEMO.C */
/* prints string at pixel location (x,y) in color c */
void
gprintf(int x, int y, int c, char *fmt, ...)
{
va_list argptr;
char str[140];
va_start(argptr, fmt);
vsprintf(str, fmt, argptr);
setcolor(c);
outtextxy(x, y, str);
setcolor(normcolr);
va_end(argptr);
}
/* ----------------------------------------------------------------------- */
/* set graphics mode; initialize various global constants */
void
initialize(void)
{
int graphdriver, graphmode;
int font=0, charsize=1;
int i,j;
detectgraph(&graphdriver, &graphmode);
if (graphdriver != EGA && graphdriver != VGA)
{
printf("\nProgram requires VGA or 256K EGA graphics capability.");
exit(1);
}
if (graphmode == VGAHI) graphmode = VGAMED; /* to allow two pages */
if (registerbgidriver(EGAVGA_driver) < 0)
{
printf("\nEGAVGA.OBJ must be included in GRAPHICS.LIB\n");
exit(1);
}
initgraph(&graphdriver, &graphmode, "");
mode = graphmode;
sxmax = getmaxx(); xscale = sxmax-10; /* xscale, yscale, ... are */
symax = getmaxy(); yscale = symax-20; /* used to convert from screen */
xscale1 = 1/xscale, yscale1 = 1/yscale; /* coords to [0,1] and back */
xb = 8; yb = symax-13; /* for graphics prompts */
setviewport( 0, 0, sxmax, symax, 1 ); /* full screen */
setfillstyle(1,10); /* use bright green for marker1 */
bar(0,0,1,1); /* draw marker1 */
block1 = malloc(14); /* size of 1X1 block1 is 14 */
getimage(0,0,1,1,block1); /* store marker1 */
putimage(0,0,block1,XOR_PUT); /* erase marker */
setfillstyle(1,12); /* use bright red for marker2 */
bar(0,0,1,1); /* draw marker2 */
block2 = malloc(14);
getimage(0,0,1,1,block2); /* store marker2 */
putimage(0,0,block2,XOR_PUT); /* erase marker2 */
for (j=1; j<=3; j++) /* draw cross (bright white) */
putpixel(5,j,15);
for (i=1; i<=3; i++)
putpixel(i,5,15);
for (i=7; i<=9; i++)
putpixel(i,5,15);
for (j=7; j<=9; j++)
putpixel(5,j,15);
cross = malloc(imagesize(0,0,8,8));
getimage(0,0,8,8,cross); /* store cross */
putimage(0,0,cross,XOR_PUT); /* erase cross */
settextstyle(font,HORIZ_DIR,charsize); /* use default font for text */
if (msinit()) /* check for and initialize mouse */
{
mouse = 1;
mshbounds(10,sxmax-10);
msvbounds(10,symax-20);
mspage(1);
}
}
/* ----------------------------------------------------------------------- */
/* mark point under crosshairs */
/* green if colr = 10, red otherwise */
void
mark(void)
{
int c;
if (np >= MAXPTS)
return; /* ignore excess points */
if (np>0 && mx[np-1]==xc && my[np-1]==yc)
return; /* don't take immediate repeat */
mx[np] = xc;
my[np] = yc;
if (np == 0)
{
if (colr==10)
putimage(xc,yc,block1,XOR_PUT); /* green marker */
else
putimage(xc,yc,block2,XOR_PUT); /* red marker */
}
if (np == 1)
{
if (colr==10)
putimage(mx[0],my[0],block1,XOR_PUT);
else
putimage(mx[0],my[0],block2,XOR_PUT);
}
if (np)
{
putimage(xc-5,yc-5,cross,XOR_PUT);
setcolor(colr);
line(mx[np-1],my[np-1],xc,yc); /* draw line from last mark */
putimage(xc-5,yc-5,cross,XOR_PUT);
}
np++;
}
/* ---------------------------------------------------------------------- */
/* change current position and CP marker */
void
move_to(int x1,int y1)
{
putimage(xc-5,yc-5,cross,XOR_PUT); /* erase current cursor mark */
xc = CLIP(x1,10,sxmax-10); /* x range is 10 to symax-10 */
yc = CLIP(y1,10,symax-20); /* y range is 10 to symax-20 */
moveto(xc,yc); /* (xc,yc) in new position */
if (mouse)
msgotoxy(xc,yc);
putimage(xc-5,yc-5,cross,XOR_PUT); /* show new cursor mark */
display(); /* show current position */
}
/* ---------------------------------------------------------------------- */
/* put prompt message at (x1,y1) */
int
prompt(int x1, int y1, int colour, char *msg)
{
int length;
length = x1+textwidth(msg);
bar(x1,y1,sxmax-1,y1+8); /* clear prompt area */
setcolor(colour);
outtextxy(x1,y1,msg); /* write message at (x1,y1) */
setcolor(normcolr); /* restore normal color */
return length+8; /* start user input 8 pixels past prompt */
}
/* ---------------------------------------------------------------------- */
/* convert from world coordinates to screen coordinates */
int
sx(double x) { return (int)(xscale*x + .5); }
int
sy(double y) { return (int)(yscale*(1-y) + .5); }
/* ---------------------------------------------------------------------- */
/* convert from screen coordinates to world coordinates */
double
wx(int x) { return xscale1*x; }
double
wy(int y) { return 1 - yscale1*y; }
/* ---------------------------------------------------------------------- */
/* ======================================================================== */
/* Mouse Functions */
/* These functions are for a Genius mouse, but they ought to work for other */
/* mouses, as well. They have the same names as the corresponding functions */
/* in Mike Smedley's CXL utilities, but are taken from the Genius manual. */
/* ======================================================================== */
int
msinit(void)
{
_AX = 0;
geninterrupt(0x33);
return _AX;
}
void
msshowcur(void)
{
_AX = 1;
geninterrupt(0x33);
}
void
mshidecur(void)
{
_AX = 2;
geninterrupt(0x33);
}
void
msstatus(int *stat, int *x, int *y) /* button press status, current x,y */
{
unsigned b;
_AX = 3;
geninterrupt(0x33);
b = _BX;
*stat = b;
*x = _CX;
*y = _DX;
}
void
msgotoxy(int x, int y) /* move mouse cursor to (x,y) pixel position */
{
_AX = 4;
_CX = x;
_DX = y;
geninterrupt(0x33);
}
int
msrelease(int button)
{
_AX = 6;
_BX = button; /* 0,1,2 = left,right,middle */
geninterrupt(0x33);
return _BX;
}
void
mshbounds(int minx, int maxx) /* limit mouse cursor horizontally */
{
_AX = 7;
_CX = minx;
_DX = maxx;
geninterrupt(0x33);
}
void
msvbounds(int miny, int maxy) /* limit mouse cursor vertically */
{
_AX = 8;
_CX = miny;
_DX = maxy;
geninterrupt(0x33);
}
void
msmotion(int *i, int *j) /* i,j are set to the x- y-motions since last call */
{
_AX = 11;
geninterrupt(0x33);
*i = _CX;
*j = _DX;
}
void
mspage(int p)
{
_AX = 29;
_BX = p;
geninterrupt(0x33);
}