home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics 16,000
/
graphics-16000.iso
/
sgi
/
editors
/
kali.lha
/
kali
/
kali.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-11
|
13KB
|
588 lines
/* */
/***** kali.c - Nina Amenta, Aug. 1989 ******/
/* */
#include <stdio.h>
#include <math.h>
#include <gl.h>
#include <device.h>
#include "symmetry.h"
#include "forms.h"
LINE *ThrowAwayLines();
void ClosestEndpoint();
WINDOW MakeButtonWindow();
LINE *NewLine();
LINE *DropLine();
LINE *GrabLine();
LINE *MakeCurrentObject();
LINE *ReadPattern();
void DrawLine();
void PickLine();
char *KeyboardIO();
void ChangeRatio();
void ChangeScale();
void ChangeAngle();
void ChangeRotation();
void SaveProc(FILE *pat);
void LoadProc(FILE *pat);
float distance();
float zoom;
RECTANGLE win_rect,sym_rect;
int mode;
POINT *sym_pts=NULL;
int count;
XFORM xforms[5];
SYMMETRY *sym;
int sym_index;
LINE *Lines=NULL;
WINDOW win;
int pick_for;
void (*xformfnc) ();
int lit;
#define QDEVICE fl_qdevice
#define QTEST fl_qtest
#define QREAD fl_qread
extern void forms_init();
#define NAMESTACKSIZE 50
main()
{
EVENT ev;
int i,j;
int ref;
FILE *pat;
LINE *cur;
POINT tmp;
short dev_data;
short namestack[NAMESTACKSIZE];
short scaled_pick;
int hits;
char *filename;
float dummy;
int old;
zoom = 1.0;
mode = 0;
sym_index = P6M;
mode = 0;
foreground();
win = MakeWindow(&win_rect);
SetUpOperatorInterface();
sym = &(SYMTAB[sym_index]);
DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
/* ortho2(0.0,zoom*win_rect.width,0.0,zoom*win_rect.height); */
count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
swapbuffers();
forms_init();
fl_do_forms();
for (;;) {
if ((mode != DRAW) && (mode != TRANSFORM) && (mode != MOVE))
ev = QREAD(&dev_data);
/* mouse handler */
else {
while (((mode == DRAW) || (mode == MOVE)) &&
((ev=QTEST()==0) || (ev == INPUTCHANGE)))
{
GetCursor(&tmp,&win_rect,zoom);
if (RectIncludesPoint(sym_rect,tmp))
{
tmp.x -= sym_pts[ref].x;
tmp.y -= sym_pts[ref].y;
VectorMatrixMult(&tmp,xforms[4],&tmp);
Lines->m[EX]=tmp.x;
Lines->m[EY]=tmp.y;
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,DrawLine);
swapbuffers();
}
}
while ((mode == TRANSFORM) && (getbutton(LEFTMOUSE)) &&
(((ev=QTEST())==0) || (ev == INPUTCHANGE)))
{
int new;
new = getvaluator(MOUSEX);
if (new>(old+1)) xformfnc(1,sym,&zoom);
else if (new<(old-1)) xformfnc(-1,sym,&zoom);
old = new;
DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
/* ortho2(0.0,zoom*win_rect.width,0.0,zoom*win_rect.height); */
count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
swapbuffers();
}
ev = QREAD(&dev_data);
}
if (ev==REDRAW)
{
reshapeviewport();
AdjustWindowRectangle(&win_rect);
DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
swapbuffers();
}
/* button handlers */
if (ev==LEFTMOUSE)
{
if (!dev_data) continue; /* do nothing on button release */
if (mode == TRANSFORM)
{
old = getvaluator(MOUSEX);
continue;
}
else if ((mode == PICK) && (pick_for == MOVE) && (lit == TRUE))
{
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,DrawLine);
swapbuffers();
mode = MOVE;
lit = FALSE;
continue;
}
/* lay down point */
GetCursor(&tmp,&win_rect,zoom);
/* if ((mode == 0) || (mode == DRAW) || (mode == MOVE)) */
{
if ((mode == DRAW) || (mode == MOVE)) /* fix endpoint */
{
POINT p;
/* Reference to closest center of symmetry */
p.x = tmp.x-sym_pts[ref].x;
p.y = tmp.y-sym_pts[ref].y;
/* Convert to standard basis */
VectorMatrixMult(&p,xforms[4],&p);
Lines->m[EX]=p.x;
Lines->m[EY]=p.y;
}
if (mode == MOVE) mode = PICK;
if (mode == 0) mode = DRAW;
if (mode == DRAW) /* start drawing new line */
{
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,DrawLine);
swapbuffers();
ref = closest(&tmp,sym_pts,count);
Lines = NewLine(Lines);
NewId(Lines);
/* Reference to closest center of symmetry */
tmp.x -= sym_pts[ref].x;
tmp.y -= sym_pts[ref].y;
/* Convert to standard basis */
VectorMatrixMult(&tmp,xforms[4],&tmp);
Lines->m[EX]=Lines->m[SX]=tmp.x;
Lines->m[EY]=Lines->m[SY]=tmp.y;
}
}
}
else if (ev==MIDDLEMOUSE) /* drop line */
{
if (!dev_data) continue; /* do nothing on button release */
if ((Lines != NULL) &&
((mode == DRAW)
|| ((mode == PICK) && (lit == TRUE) && (pick_for == CUT)) ))
{
Lines = DropLine(Lines);
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,DrawLine);
swapbuffers();
mode = (mode == DRAW) ? 0 : PICK;
lit = FALSE;
}
}
else if (ev == RIGHTMOUSE) /* pick */
{
if (!dev_data) continue; /* do nothing on button release */
if (mode != PICK) continue;
scaled_pick = zoom*10+1;
picksize(scaled_pick,scaled_pick);
pick(namestack,NAMESTACKSIZE);
ortho2(0.0,zoom*win_rect.width,0.0,
zoom*win_rect.height);
initnames();
pushname(-1); /* placeholders for first line */
pushname(-1);
pushname(-1);
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,PickLine);
hits = endpick(namestack);
ortho2(0.0,zoom*win_rect.width,0.0,
zoom*win_rect.height);
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,DrawLine);
if (hits > 0)
{
i = 0;
while (namestack[4*i+1] == -1) i++;
if (i >= hits) continue;
Lines = GrabLine(namestack[4*i+2],Lines);
if (pick_for == MOVE)
{
/* get correct rot & ref */
UseRightCopy(Lines,sym,xforms,namestack[4*i+3]);
ref = namestack[4*i+1]; /* correct translation */
/* get cursor relative to ref */
GetCursor(&tmp,&win_rect,zoom);
tmp.x -= sym_pts[ref].x;
tmp.y -= sym_pts[ref].y;
/* Convert to standard basis */
VectorMatrixMult(&tmp,xforms[4],&tmp);
ClosestEndpoint(Lines,&tmp);
HighLiteLine(&sym_rect,Lines,sym,
sym_pts,xforms,count,MAGENTA);
}
else /* for delete - just lite up */
{
HighLiteLine(&sym_rect,Lines,sym,
sym_pts,xforms,count,GREEN);
}
lit = TRUE;
}
else lit = FALSE;
swapbuffers();
}
fl_do_forms();
}
}
void ChangeScale(direction,sym,zoom)
int direction;
SYMMETRY *sym;
float *zoom;
{
if (direction == 1) *zoom *= 0.95;
else *zoom *= 1.05;
}
void ChangeRotation(direction,sym,zoom)
int direction;
SYMMETRY *sym;
float *zoom;
{
double angle;
XFORM rotation;
if (direction == 1) angle = M_PI / 180;
else angle = - M_PI / 180;
SetUpRot(angle,rotation);
VectorMatrixMult(&(sym->v1),rotation,&(sym->v1));
VectorMatrixMult(&(sym->v2),rotation,&(sym->v2));
}
void ChangeRatio(direction,sym,zoom)
int direction;
SYMMETRY *sym;
float *zoom;
{
if (direction == 1) VectorScalarMult(&sym->v1,1.1);
else VectorScalarMult(&sym->v1,0.95);
}
void ChangeAngle(direction,sym,zoom)
int direction;
SYMMETRY *sym;
float *zoom;
{
double angle;
XFORM rotation;
if (direction == 1) angle = M_PI / 360;
else angle = - M_PI / 360;
SetUpRot(angle,rotation);
VectorMatrixMult(&(sym->v1),rotation,&(sym->v1));
/* modify rotation matrix for opposite angle */
rotation[1] = -rotation[1];
rotation[2] = -rotation[2];
VectorMatrixMult(&(sym->v2),rotation,&(sym->v2));
}
/* Move the selected line to first in the list */
LINE *GrabLine(i,first)
short i;
LINE *first;
{
LINE *cur,*last;
last = NULL; /* previous line we looked at, NOT last in the list */
for (cur=first; cur != NULL; cur=cur->next)
{
if (cur->id == i)
{
if (last != NULL)
{
last->next = cur->next;
cur->next = first;
}
first = cur;
break;
}
last = cur;
}
return(first);
}
LINE *DropLine(L)
LINE *L;
{
LINE *cur;
cur = L->next;
free(L);
return(cur);
}
SetUpOperatorInterface()
{
QDEVICE(LEFTMOUSE);
QDEVICE(MIDDLEMOUSE);
QDEVICE(RIGHTMOUSE);
}
GetCursor(p,r,zoom)
POINT *p;
RECTANGLE *r;
float zoom;
{
p->x = (getvaluator(MOUSEX)-r->x)*zoom;
p->y = (getvaluator(MOUSEY)-r->y)*zoom;
}
DrawCurrent(rect,Lines,sym,pts,xforms,count,drawing_routine)
RECTANGLE *rect;
LINE *Lines;
SYMMETRY *sym;
POINT *pts;
XFORM *xforms;
int count;
void (*drawing_routine) ();
{
LINE *obj;
RECTANGLE bounds;
winset(win);
obj = MakeCurrentObject(Lines,sym,xforms,&bounds);
color(WHITE);
clear();
color(BLACK);
DrawPoints(pts,count);
color(BLUE);
ReplicateObject
(rect,obj,pts,count,&bounds,&(sym->v1),&(sym->v2),drawing_routine);
FreeObject(obj);
}
HighLiteLine(rect,cur,sym,pts,xforms,count,colour)
RECTANGLE *rect;
LINE *cur;
SYMMETRY *sym;
POINT *pts;
XFORM *xforms;
int count;
Colorindex colour; /* note attractive British spelling */
{
LINE *obj,*temp;
RECTANGLE bounds;
winset(win);
temp = cur->next;
cur->next = NULL;
obj = MakeCurrentObject(cur,sym,xforms,&bounds);
cur->next = temp;
color(colour);
ReplicateObject
(rect,obj,pts,count,&bounds,&(sym->v1),&(sym->v2),DrawLine);
FreeObject(obj);
}
/* UseRightCopy - changes the endpoints of the line cur according
to the pos'th transformation that goes into making an object.
Since all transformations of a given line are eqivalent, this makes
no difference in the picture */
UseRightCopy(cur,sym,xforms,pos)
LINE *cur;
SYMMETRY *sym;
XFORM *xforms;
short pos;
{
RECTANGLE bounds;
LINE *temp,*l,*obj;
temp = cur->next;
cur->next = NULL;
obj = MakeCurrentObject(cur,sym,xforms,&bounds);
for (l = obj; l->next != NULL; l = l->next) {
if (l->obj_pos == pos) break;
}
*cur = *l; /* copy line description */
FreeObject(obj);
MatrixMultiply(cur->m,xforms[4],cur->m);
cur->next = temp;
}
WINDOW MakeWindow(r)
RECTANGLE *r;
{
WINDOW rwin;
prefposition(233, 839, 8, 622);
rwin = winopen("kali");
minsize(32,32);
maxsize(1024, 1280);
winconstraints();
AdjustWindowRectangle(r);
doublebuffer();
gconfig();
return(rwin);
}
AdjustWindowRectangle(r)
RECTANGLE *r;
{
long x,y;
getorigin(&x,&y);
r->x = x; r->y = y;
getsize(&x,&y);
r->width = x;
r->height = y;
}
/* Find closest center of symmetry to new motif point */
int closest(new_pt,pts,maxpts)
POINT *new_pt;
POINT *pts;
int maxpts;
{
int i,min_i;
float dist,min=HUGE;
for (i=0; i<maxpts; i++)
{
dist = distance(new_pt->x, new_pt->y, pts[i].x, pts[i].y);
if (dist < min) { min = dist; min_i = i; }
}
return(min_i);
}
PrintLine(l)
LINE* l;
{
int i;
printf("%x ",l);
for (i=0;i<4;i++) printf("%6.3f ",l->m[i]);
printf("%d %x \n",l->id,l->next);
}
DumpLines(Lines)
LINE* Lines;
{
LINE* cur;
int i;
i = 0;
for (cur=Lines; cur != NULL; cur=cur->next)
{
printf("Line %d ",i++);
PrintLine(cur);
}
}
complain(win_rect,zoom)
RECTANGLE *win_rect;
float zoom;
{
KeyboardIO(0,20.0,win_rect->height-20.0,
"Bogus file name!",zoom);
sleep(3);
}
LINE* ThrowAwayLines(Lines)
LINE *Lines;
{
LINE *cur;
for (cur=Lines; cur!=NULL; cur=cur->next)
free(cur);
return(NULL);
}
void SaveProc(FILE *pat)
{
LINE *cur;
fprintf(pat,"%d\n",sym_index);
fprintf(pat,"%6.3f %6.3f\n",
sym_rect.width,sym_rect.height);
fprintf(pat,"%6.3f %6.3f\n",
sym->v1.x,sym->v1.y);
fprintf(pat,"%6.3f %6.3f\n",
sym->v2.x,sym->v2.y);
fprintf(pat,"%6.3f \n",
zoom);
for (cur=Lines; cur != NULL; cur=cur->next)
fprintf(pat,"%6.3f %6.3f %6.3f %6.3f\n",
cur->m[0],cur->m[1],cur->m[2],cur->m[3]);
fclose(pat);
}
void LoadProc(FILE *pat)
{
float dummy;
fscanf(pat,"%d\n",&sym_index);
fscanf(pat,"%f %f\n",&dummy,&dummy);
sym = &(SYMTAB[sym_index]);
fscanf(pat,"%f %f\n",
&(sym->v1.x),&(sym->v1.y));
fscanf(pat,"%f %f\n",
&(sym->v2.x),&(sym->v2.y));
fscanf(pat,"%f \n",
&zoom);
DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
/* ortho2(0.0,zoom*win_rect.width,0.0,
zoom*win_rect.height); */
count = SetUpSymmetry(sym,&sym_pts,
xforms,&sym_rect);
Lines = ThrowAwayLines(Lines);
Lines = ReadPattern(Lines,pat);
DrawCurrent(&sym_rect,Lines,sym,
sym_pts,xforms,count,DrawLine);
swapbuffers();
mode = 0;
}