home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / sgi / editors / kali.lha / kali / kali.c < prev    next >
C/C++ Source or Header  |  1992-10-11  |  13KB  |  588 lines

  1. /*                        */
  2. /***** kali.c - Nina Amenta, Aug. 1989 ******/
  3. /*                        */
  4. #include <stdio.h>
  5. #include <math.h>
  6. #include <gl.h>
  7. #include <device.h>
  8. #include "symmetry.h"
  9. #include "forms.h"
  10.  
  11. LINE *ThrowAwayLines();
  12. void ClosestEndpoint();
  13. WINDOW MakeButtonWindow();
  14. LINE *NewLine();
  15. LINE *DropLine();
  16. LINE *GrabLine();
  17. LINE *MakeCurrentObject();
  18. LINE *ReadPattern();
  19. void DrawLine();
  20. void PickLine();
  21. char *KeyboardIO();
  22. void ChangeRatio();
  23. void ChangeScale();
  24. void ChangeAngle();
  25. void ChangeRotation();
  26. void SaveProc(FILE *pat);
  27. void LoadProc(FILE *pat);
  28. float distance();
  29.  
  30. float zoom;
  31. RECTANGLE win_rect,sym_rect;
  32. int mode;
  33. POINT *sym_pts=NULL;
  34. int count;
  35. XFORM xforms[5];
  36. SYMMETRY *sym;
  37. int sym_index;
  38. LINE *Lines=NULL;
  39. WINDOW win;
  40. int pick_for;
  41. void (*xformfnc) ();
  42. int lit;
  43.  
  44. #define QDEVICE    fl_qdevice
  45. #define QTEST    fl_qtest
  46. #define QREAD    fl_qread
  47.  
  48. extern void forms_init();
  49.  
  50. #define NAMESTACKSIZE 50
  51.  
  52. main()
  53. {
  54.   EVENT ev;
  55.   int i,j;
  56.   int ref;
  57.   FILE *pat;
  58.   LINE *cur;
  59.   POINT tmp;
  60.   short dev_data;
  61.   short namestack[NAMESTACKSIZE];
  62.   short scaled_pick;
  63.   int hits;
  64.   char *filename;
  65.   float dummy;
  66.   int old;
  67.   
  68.   zoom = 1.0;
  69.   mode = 0;
  70.   sym_index = P6M;
  71.   mode = 0;
  72.   
  73.   foreground();
  74.   
  75.   win = MakeWindow(&win_rect);
  76.   SetUpOperatorInterface();
  77.   sym = &(SYMTAB[sym_index]);
  78.   DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
  79.   /*   ortho2(0.0,zoom*win_rect.width,0.0,zoom*win_rect.height); */
  80.   count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
  81.   DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
  82.   swapbuffers();
  83.   
  84.   forms_init(); 
  85.   fl_do_forms();
  86.  
  87.   for (;;)    {
  88.     if ((mode != DRAW) && (mode != TRANSFORM) && (mode != MOVE)) 
  89.       ev = QREAD(&dev_data);
  90.     
  91.     /* mouse handler */
  92.     else {
  93.       while (((mode == DRAW) || (mode == MOVE)) && 
  94.          ((ev=QTEST()==0) || (ev == INPUTCHANGE)))
  95.     {
  96.       GetCursor(&tmp,&win_rect,zoom);
  97.       if (RectIncludesPoint(sym_rect,tmp))
  98.         {
  99.           tmp.x -= sym_pts[ref].x;
  100.           tmp.y -= sym_pts[ref].y;
  101.           VectorMatrixMult(&tmp,xforms[4],&tmp);
  102.           Lines->m[EX]=tmp.x;
  103.           Lines->m[EY]=tmp.y;
  104.           DrawCurrent(&sym_rect,Lines,sym,
  105.               sym_pts,xforms,count,DrawLine);
  106.           swapbuffers();
  107.         }
  108.     }
  109.       while ((mode == TRANSFORM) && (getbutton(LEFTMOUSE)) && 
  110.          (((ev=QTEST())==0) || (ev == INPUTCHANGE)))
  111.     {
  112.       int new;
  113.       new = getvaluator(MOUSEX);
  114.       if (new>(old+1)) xformfnc(1,sym,&zoom);
  115.       else if (new<(old-1)) xformfnc(-1,sym,&zoom);
  116.       old = new;
  117.       DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
  118.       /*       ortho2(0.0,zoom*win_rect.width,0.0,zoom*win_rect.height); */
  119.       count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
  120.       DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
  121.       swapbuffers();
  122.     }
  123.       
  124.       ev = QREAD(&dev_data);
  125.     }
  126.  
  127.     if (ev==REDRAW)
  128.       {
  129.     reshapeviewport();
  130.     AdjustWindowRectangle(&win_rect);
  131.     DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
  132.     count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
  133.     DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
  134.     swapbuffers();
  135.       }
  136.     
  137.     
  138.     /* button handlers */
  139.     
  140.     if (ev==LEFTMOUSE)  
  141.       {
  142.     if (!dev_data) continue;   /* do nothing on button release */
  143.     if (mode == TRANSFORM) 
  144.       {
  145.         old = getvaluator(MOUSEX);
  146.         continue;
  147.       }
  148.     else if ((mode == PICK) && (pick_for == MOVE) && (lit == TRUE))
  149.       {
  150.         DrawCurrent(&sym_rect,Lines,sym,
  151.             sym_pts,xforms,count,DrawLine);
  152.         swapbuffers();
  153.         mode = MOVE;
  154.         lit = FALSE;
  155.         continue;
  156.       }
  157.     
  158.     /* lay down point */
  159.     GetCursor(&tmp,&win_rect,zoom);
  160.     
  161.     /*       if ((mode == 0) || (mode == DRAW) || (mode == MOVE)) */
  162.     {
  163.       if ((mode == DRAW) || (mode == MOVE)) /* fix endpoint */
  164.         {
  165.           POINT p;
  166.           /* Reference to closest center of symmetry */
  167.           p.x = tmp.x-sym_pts[ref].x;
  168.           p.y = tmp.y-sym_pts[ref].y;
  169.           /* Convert to standard basis */
  170.           VectorMatrixMult(&p,xforms[4],&p);
  171.           Lines->m[EX]=p.x;
  172.           Lines->m[EY]=p.y;
  173.         }
  174.       if (mode == MOVE) mode = PICK;
  175.       if (mode == 0) mode = DRAW;
  176.       if (mode == DRAW)  /* start drawing new line */
  177.         {
  178.           DrawCurrent(&sym_rect,Lines,sym,
  179.               sym_pts,xforms,count,DrawLine);
  180.           swapbuffers();
  181.           ref = closest(&tmp,sym_pts,count);
  182.           Lines = NewLine(Lines);
  183.           NewId(Lines);
  184.           /* Reference to closest center of symmetry */
  185.           tmp.x -= sym_pts[ref].x;
  186.           tmp.y -= sym_pts[ref].y;
  187.           /* Convert to standard basis */
  188.           VectorMatrixMult(&tmp,xforms[4],&tmp);
  189.           Lines->m[EX]=Lines->m[SX]=tmp.x;
  190.           Lines->m[EY]=Lines->m[SY]=tmp.y;
  191.         }
  192.     }
  193.       }
  194.     
  195.     
  196.     else if (ev==MIDDLEMOUSE)   /* drop line */
  197.       {
  198.     if (!dev_data) continue;   /* do nothing on button release */
  199.     if ((Lines != NULL) && 
  200.         ((mode == DRAW) 
  201.          || ((mode == PICK) && (lit == TRUE) && (pick_for == CUT)) ))
  202.       {
  203.         Lines = DropLine(Lines);
  204.         DrawCurrent(&sym_rect,Lines,sym,
  205.             sym_pts,xforms,count,DrawLine);
  206.         swapbuffers();
  207.         mode = (mode == DRAW) ? 0 : PICK;
  208.         lit = FALSE;
  209.       }
  210.       }
  211.     
  212.     else if (ev == RIGHTMOUSE)  /* pick */
  213.       {
  214.     if (!dev_data) continue;   /* do nothing on button release */
  215.     if (mode != PICK) continue;
  216.     
  217.     scaled_pick = zoom*10+1;
  218.     picksize(scaled_pick,scaled_pick);
  219.     pick(namestack,NAMESTACKSIZE);
  220.     ortho2(0.0,zoom*win_rect.width,0.0,
  221.            zoom*win_rect.height);
  222.     initnames();
  223.     pushname(-1);  /* placeholders for first line */ 
  224.     pushname(-1);
  225.     pushname(-1);
  226.     DrawCurrent(&sym_rect,Lines,sym,
  227.             sym_pts,xforms,count,PickLine);
  228.     hits = endpick(namestack);
  229.     ortho2(0.0,zoom*win_rect.width,0.0,
  230.            zoom*win_rect.height);
  231.     DrawCurrent(&sym_rect,Lines,sym,
  232.             sym_pts,xforms,count,DrawLine);
  233.     
  234.     if (hits > 0)
  235.       {
  236.         i = 0;
  237.         while (namestack[4*i+1] == -1) i++;
  238.         if (i >= hits) continue;
  239.         Lines = GrabLine(namestack[4*i+2],Lines);
  240.         if (pick_for == MOVE)
  241.           {
  242.         /* get correct rot & ref */
  243.         UseRightCopy(Lines,sym,xforms,namestack[4*i+3]);
  244.         ref = namestack[4*i+1];   /* correct translation */
  245.         /* get cursor relative to ref */
  246.         GetCursor(&tmp,&win_rect,zoom);
  247.         tmp.x -= sym_pts[ref].x;
  248.         tmp.y -= sym_pts[ref].y;
  249.         /* Convert to standard basis */
  250.         VectorMatrixMult(&tmp,xforms[4],&tmp);
  251.         ClosestEndpoint(Lines,&tmp);
  252.         HighLiteLine(&sym_rect,Lines,sym,
  253.                  sym_pts,xforms,count,MAGENTA);
  254.           }
  255.         else /* for delete - just lite up */
  256.           {
  257.         HighLiteLine(&sym_rect,Lines,sym,
  258.                  sym_pts,xforms,count,GREEN);
  259.           }
  260.         lit = TRUE;
  261.       }
  262.     else lit = FALSE;
  263.     swapbuffers();
  264.       }
  265.     fl_do_forms();
  266.   }
  267. }
  268.     
  269.  
  270. void ChangeScale(direction,sym,zoom)
  271. int direction;
  272. SYMMETRY *sym;
  273. float *zoom;
  274. {
  275.   if (direction == 1) *zoom *= 0.95;
  276.   else *zoom *= 1.05;
  277. }
  278.  
  279. void ChangeRotation(direction,sym,zoom)
  280. int direction;
  281. SYMMETRY *sym;
  282. float *zoom;
  283. {
  284.   double angle;
  285.   XFORM rotation;
  286.  
  287.   if (direction == 1) angle = M_PI / 180;
  288.   else angle = - M_PI / 180;
  289.   SetUpRot(angle,rotation);
  290.   VectorMatrixMult(&(sym->v1),rotation,&(sym->v1));
  291.   VectorMatrixMult(&(sym->v2),rotation,&(sym->v2));
  292. }
  293.  
  294. void ChangeRatio(direction,sym,zoom)
  295. int direction;
  296. SYMMETRY *sym;
  297. float *zoom;
  298. {
  299.   if (direction == 1) VectorScalarMult(&sym->v1,1.1);
  300.   else VectorScalarMult(&sym->v1,0.95);
  301. }
  302.  
  303. void ChangeAngle(direction,sym,zoom)
  304. int direction;
  305. SYMMETRY *sym;
  306. float *zoom;
  307. {
  308.   double angle;
  309.   XFORM rotation;
  310.  
  311.   if (direction == 1) angle = M_PI / 360;
  312.   else angle = - M_PI / 360;
  313.   SetUpRot(angle,rotation);
  314.   VectorMatrixMult(&(sym->v1),rotation,&(sym->v1));
  315.   /* modify rotation matrix for opposite angle */
  316.   rotation[1] = -rotation[1];
  317.   rotation[2] = -rotation[2];
  318.   VectorMatrixMult(&(sym->v2),rotation,&(sym->v2));
  319. }
  320.  
  321.  
  322. /* Move the selected line to first in the list */
  323. LINE *GrabLine(i,first)
  324. short i;
  325. LINE *first;
  326. {
  327. LINE *cur,*last;
  328.  
  329.     last = NULL;  /* previous line we looked at, NOT last in the list */
  330.     for (cur=first; cur != NULL; cur=cur->next)
  331.       {
  332.     if (cur->id == i)
  333.         {
  334.         if (last != NULL) 
  335.             {
  336.             last->next = cur->next;
  337.             cur->next = first;
  338.             }
  339.         first = cur;
  340.         break;
  341.         }
  342.     last = cur;      
  343.       }
  344.     return(first);
  345. }
  346.  
  347.  
  348. LINE *DropLine(L)
  349. LINE *L;
  350. {
  351. LINE *cur;
  352.      cur = L->next;
  353.      free(L);
  354.      return(cur);
  355. }
  356.  
  357.  
  358. SetUpOperatorInterface()
  359. {
  360.   QDEVICE(LEFTMOUSE);
  361.   QDEVICE(MIDDLEMOUSE);
  362.   QDEVICE(RIGHTMOUSE);
  363. }
  364.  
  365.  
  366. GetCursor(p,r,zoom)
  367. POINT *p;
  368. RECTANGLE *r;
  369. float zoom;
  370. {
  371.   p->x = (getvaluator(MOUSEX)-r->x)*zoom;
  372.   p->y = (getvaluator(MOUSEY)-r->y)*zoom;
  373. }
  374.  
  375.  
  376.  
  377. DrawCurrent(rect,Lines,sym,pts,xforms,count,drawing_routine)
  378. RECTANGLE *rect;
  379. LINE *Lines;
  380. SYMMETRY *sym;
  381. POINT *pts;
  382. XFORM *xforms;
  383. int count;
  384. void (*drawing_routine) ();
  385. {
  386.   LINE *obj;
  387.   RECTANGLE bounds;
  388.  
  389.   winset(win); 
  390.   obj = MakeCurrentObject(Lines,sym,xforms,&bounds);
  391.   color(WHITE);
  392.   clear();
  393.   color(BLACK);
  394.   DrawPoints(pts,count);
  395.   color(BLUE);
  396.   ReplicateObject
  397.     (rect,obj,pts,count,&bounds,&(sym->v1),&(sym->v2),drawing_routine);
  398.   FreeObject(obj);
  399. }
  400.  
  401. HighLiteLine(rect,cur,sym,pts,xforms,count,colour)
  402. RECTANGLE *rect;
  403. LINE *cur;
  404. SYMMETRY *sym;
  405. POINT *pts;
  406. XFORM *xforms;
  407. int count;
  408. Colorindex colour;  /* note attractive British spelling */
  409. {
  410.     LINE *obj,*temp;
  411.     RECTANGLE bounds;
  412.  
  413.     winset(win);
  414.     temp = cur->next;
  415.     cur->next = NULL;
  416.     obj = MakeCurrentObject(cur,sym,xforms,&bounds);
  417.     cur->next = temp;
  418.     color(colour);
  419.     ReplicateObject
  420.       (rect,obj,pts,count,&bounds,&(sym->v1),&(sym->v2),DrawLine);
  421.     FreeObject(obj);
  422. }
  423.  
  424.  
  425.  
  426. /* UseRightCopy - changes the endpoints of the line cur according 
  427. to the pos'th transformation that goes into making an object.
  428. Since all transformations of a given line are eqivalent, this makes
  429. no difference in the picture */
  430.  
  431. UseRightCopy(cur,sym,xforms,pos)
  432. LINE *cur;
  433. SYMMETRY *sym;
  434. XFORM *xforms;
  435. short pos;
  436. {
  437.   RECTANGLE bounds;
  438.   LINE *temp,*l,*obj;
  439.  
  440.     temp = cur->next;
  441.     cur->next = NULL;
  442.     obj = MakeCurrentObject(cur,sym,xforms,&bounds);
  443.     for (l = obj; l->next != NULL; l = l->next) {
  444.       if (l->obj_pos == pos) break;
  445.     }
  446.     *cur = *l;        /* copy line description */
  447.     FreeObject(obj);
  448.     MatrixMultiply(cur->m,xforms[4],cur->m);
  449.     cur->next = temp;
  450. }
  451.  
  452.  
  453. WINDOW MakeWindow(r)
  454. RECTANGLE *r;
  455. {
  456.   WINDOW rwin;
  457.  
  458.     prefposition(233, 839, 8, 622);
  459.     rwin = winopen("kali");
  460.     minsize(32,32);
  461.     maxsize(1024, 1280);
  462.     winconstraints();
  463.     AdjustWindowRectangle(r);
  464.     doublebuffer();
  465.     gconfig();
  466.     return(rwin);
  467. }
  468.  
  469. AdjustWindowRectangle(r)
  470. RECTANGLE *r;
  471. {
  472.   long x,y;
  473.  
  474.     getorigin(&x,&y);
  475.     r->x = x; r->y = y;
  476.     getsize(&x,&y);
  477.     r->width = x; 
  478.     r->height = y;
  479. }
  480.  
  481.  
  482.   
  483. /* Find closest center of symmetry to new motif point */
  484. int closest(new_pt,pts,maxpts)
  485. POINT *new_pt;
  486. POINT *pts;
  487. int maxpts;
  488. {
  489.   int i,min_i;
  490.   float dist,min=HUGE;
  491.  
  492.   for (i=0; i<maxpts; i++)
  493.     {
  494.       dist = distance(new_pt->x, new_pt->y, pts[i].x, pts[i].y);
  495.       if (dist < min) {    min = dist; min_i = i; }
  496.     }
  497.   return(min_i);
  498. }
  499.  
  500. PrintLine(l)
  501. LINE* l;
  502. {
  503. int i;
  504.     printf("%x ",l);
  505.     for (i=0;i<4;i++)   printf("%6.3f ",l->m[i]);
  506.     printf("%d %x \n",l->id,l->next);
  507. }
  508.  
  509. DumpLines(Lines)
  510. LINE* Lines;
  511. {
  512.   LINE* cur;    
  513.   int i;
  514.   i = 0;
  515.   for (cur=Lines; cur != NULL; cur=cur->next)
  516.     {
  517.     printf("Line %d  ",i++);
  518.     PrintLine(cur);
  519.     }
  520. }
  521.  
  522. complain(win_rect,zoom)
  523. RECTANGLE *win_rect;
  524. float zoom;
  525. {
  526.    KeyboardIO(0,20.0,win_rect->height-20.0,
  527.         "Bogus file name!",zoom);
  528.    sleep(3);
  529. }
  530.  
  531.  
  532. LINE* ThrowAwayLines(Lines)
  533. LINE *Lines;
  534. {
  535.   LINE *cur;
  536.   for (cur=Lines; cur!=NULL; cur=cur->next)
  537.     free(cur);
  538.   return(NULL);
  539. }
  540.  
  541.  
  542. void SaveProc(FILE *pat)
  543. {
  544.   LINE *cur;
  545.  
  546.   fprintf(pat,"%d\n",sym_index);
  547.   fprintf(pat,"%6.3f %6.3f\n",
  548.       sym_rect.width,sym_rect.height);
  549.   fprintf(pat,"%6.3f %6.3f\n",
  550.       sym->v1.x,sym->v1.y);
  551.   fprintf(pat,"%6.3f %6.3f\n",
  552.       sym->v2.x,sym->v2.y);
  553.   fprintf(pat,"%6.3f \n",
  554.       zoom);
  555.   for (cur=Lines; cur != NULL; cur=cur->next)
  556.     fprintf(pat,"%6.3f %6.3f %6.3f %6.3f\n",
  557.         cur->m[0],cur->m[1],cur->m[2],cur->m[3]);
  558.   fclose(pat);
  559. }
  560.  
  561. void LoadProc(FILE *pat)
  562. {
  563.   float dummy;
  564.   fscanf(pat,"%d\n",&sym_index);
  565.   fscanf(pat,"%f %f\n",&dummy,&dummy);
  566.   sym = &(SYMTAB[sym_index]);
  567.   fscanf(pat,"%f %f\n",
  568.      &(sym->v1.x),&(sym->v1.y));
  569.   fscanf(pat,"%f %f\n",
  570.      &(sym->v2.x),&(sym->v2.y));
  571.   fscanf(pat,"%f \n",
  572.      &zoom);
  573.   DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
  574.   /*                ortho2(0.0,zoom*win_rect.width,0.0,
  575.                 zoom*win_rect.height); */
  576.   count = SetUpSymmetry(sym,&sym_pts,
  577.             xforms,&sym_rect);
  578.   Lines = ThrowAwayLines(Lines);
  579.   Lines = ReadPattern(Lines,pat);
  580.  
  581.  
  582.   DrawCurrent(&sym_rect,Lines,sym,
  583.           sym_pts,xforms,count,DrawLine);
  584.   swapbuffers();
  585.   mode = 0;
  586. }
  587.  
  588.