home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 038.lha / Bezier.c / bezier.c
C/C++ Source or Header  |  1987-05-16  |  7KB  |  372 lines

  1.  
  2. /*
  3.  *  BEZIER.C
  4.  *
  5.  *  Matthew Dillon.
  6.  *  Public Domain (no Copyrights whatsoever)
  7.  *
  8.  *  -Assumes AZTEC compilation,  +L (32 bit ints), with all AMIGA symbols
  9.  *  precompiled.  Additionally expects certain typedefs and routines
  10.  *  found in MY.LIB, as well as some MY.LIB #include files.
  11.  *
  12.  *  An experienced programmer can remove the MY.LIB dependancies
  13.  *  (openlibs() call), and figure out what typedefs have been assumed if
  14.  *  he wishes to compile the program.  You can also simply extract the
  15.  *  Bezier functions for your own use.
  16.  *
  17.  *  BEZIER EQUATIONS:
  18.  *
  19.  *    c(t) = T(t)BP
  20.  *
  21.  *    T(t) = (t^3 t^2 t 1)        P= ( P1 )
  22.  *    B = (  -1   3  -3   1    )       ( P2 )
  23.  *        (    3  -6    3   0    )       ( P3 )
  24.  *        (  -3   3    0   0    )       ( P4 )
  25.  *        (    1   0    0   0    )
  26.  *
  27.  *    t:  range 0 to 1
  28.  *    C:  coordinate matrix  1xD matrix (D = dimensions)
  29.  *    B:  Bezier matrix      4x4
  30.  *    P:  Ctrl. Point matrix 4xD matrix (D = dimensions)
  31.  *
  32.  *    using D = 2
  33.  */
  34.  
  35. #include <typedefs.h>
  36. #include <xmisc.h>
  37.  
  38. #define     SHIFTS  9
  39. #define     ONE     (1<<SHIFTS)
  40.  
  41. typedef struct PropInfo XPI;
  42. typedef struct Image    IM;
  43.  
  44. extern IMESS *GetMsg();
  45.  
  46. #define MYGADGETS   (WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE)
  47.  
  48. NW Nw = {
  49.     64, 64, 320, 100,
  50.     0, 1,
  51.     NEWSIZE|MOUSEBUTTONS|MOUSEMOVE|CLOSEWINDOW|GADGETDOWN|GADGETUP,
  52.     MYGADGETS|REPORTMOUSE|ACTIVATE|NOCAREREFRESH,
  53.     0, 0, (UBYTE *)"Bezier, By Matthew Dillon", NULL, NULL,
  54.     32, 64, -1, -1, WBENCHSCREEN
  55. };
  56.  
  57. WIN *Win;
  58. RP  *Rp;
  59. short Ux, Uy, Lx, Ly;
  60. short Step = 128;
  61.  
  62. main(ac, av)
  63. char *av[];
  64. {
  65.     register IMESS *mess;
  66.     short notdone = 1;
  67.     short pt = -1;
  68.     short ptarray[4][2];
  69.     short auarray[4][2];    /* auto move */
  70.     short au = 0;
  71.     long  delay = 0;
  72.  
  73.     short gy, gg = 0;
  74.     XPI *po;
  75.  
  76.     if (ac >= 2) {
  77.     if (ac >= 3)
  78.         delay = atoi(av[2]);
  79.     au = 1;
  80.     loadauto(auarray, atoi(av[1]));
  81.     }
  82.  
  83.     init_gadgets(&Nw, &po);
  84.     exiterr(!openlibs(INTUITION_LIB|GRAPHICS_LIB), "unable to open libs");
  85.     exiterr(!(Win = OpenWindow(&Nw)), "unable to open window");
  86.     Rp = Win->RPort;
  87.     SetAPen(Rp, 1);
  88.     setpoint(ptarray, 0, 32, 32);
  89.     setpoint(ptarray, 1, 40, 40);
  90.     setpoint(ptarray, 2, 50, 50);
  91.     setpoint(ptarray, 3, 60, 60);
  92.     setbounds(ptarray);
  93.     while (notdone) {
  94.     short mx, my, mm = 0;
  95.     if (au == 0) {
  96.         WaitPort(Win->UserPort);
  97.     } else {
  98.         if (delay)
  99.         Delay(delay);
  100.         moveauto(auarray, ptarray);
  101.     }
  102.     while (mess = GetMsg(Win->UserPort)) {
  103.         switch(mess->Class) {
  104.         case CLOSEWINDOW:
  105.         notdone = 0;
  106.         break;
  107.         case NEWSIZE:
  108.         setbounds(ptarray);
  109.         break;
  110.         case GADGETUP:
  111.         case GADGETDOWN:
  112.         {
  113.             gg = mess->Class;
  114.             gy = po->VertPot / 256;
  115.         }
  116.         break;
  117.         case MOUSEBUTTONS:
  118.         switch(mess->Code) {
  119.         case SELECTDOWN:
  120.             pt = getpoint(ptarray, mess->MouseX, mess->MouseY);
  121.             movepoint(ptarray, pt, mess->MouseX, mess->MouseY);
  122.             drawcurve(ptarray);
  123.             break;
  124.         case SELECTUP:
  125.             pt = -1;
  126.             break;
  127.         }
  128.         break;
  129.         case MOUSEMOVE:
  130.         if (gg == GADGETDOWN) {
  131.             gy = po->VertPot / 256;
  132.             break;
  133.         }
  134.         mm = 1;
  135.         mx = mess->MouseX;
  136.         my = mess->MouseY;
  137.         break;
  138.         default:
  139.         break;
  140.         }
  141.         ReplyMsg(mess);
  142.     }
  143.     if (mm && pt >= 0) {
  144.         movepoint(ptarray, pt, mx, my);
  145.         drawcurve(ptarray);
  146.     }
  147.     if (gg) {
  148.         char buf[32];
  149.         if (gg == GADGETUP)
  150.         gg = 0;
  151.         if (gy + 1 >= 0 && gy + 1 != Step) {
  152.         Step = gy + 1;
  153.         sprintf(buf, "gran: %4ld/%ld", Step, ONE);
  154.         drawcurve(ptarray);
  155.         Move(Rp, Ux + 1, Uy + 16);
  156.         Text(Rp, buf, strlen(buf));
  157.         }
  158.     }
  159.     }
  160.     exiterr(1, NULL);
  161. }
  162.  
  163. exiterr(n, str)
  164. char *str;
  165. {
  166.     if (n) {
  167.     if (str)
  168.         puts(str);
  169.     if (Win)
  170.         CloseWindow(Win);
  171.     closelibs(-1);
  172.     exit(1);
  173.     }
  174. }
  175.  
  176. setbounds(a)
  177. register long *a;
  178. {
  179.     Ux = Win->BorderLeft;
  180.     Uy = Win->BorderTop;
  181.     Lx = Win->Width - Win->BorderRight;
  182.     Ly = Win->Height- Win->BorderBottom + 1;
  183.     drawcurve(a);
  184. }
  185.  
  186. setpoint(a, pt, x, y)
  187. register short a[4][2];
  188. {
  189.     a[pt][0] = x;
  190.     a[pt][1] = y;
  191.     drawpoints(a, pt, pt + 1);
  192. }
  193.  
  194. getpoint(a, x, y)
  195. register short a[4][2];
  196. {
  197.     register short i, bi;
  198.     register long r, br;
  199.  
  200.     for (i = bi = 0, br = 0x7FFFFFFF; i < 4; ++i) {
  201.     r = (x-a[i][0])*(x-a[i][0]) + (y-a[i][1])*(y-a[i][1]);
  202.     if (r < br) {
  203.         bi = i;
  204.         br = r;
  205.     }
  206.     }
  207.     return(bi);
  208. }
  209.  
  210. movepoint(a, pt, x, y)
  211. register short a[4][2];
  212. {
  213.     SetAPen(Rp, 0);
  214.     drawpoints(a, pt, pt + 1);
  215.     SetAPen(Rp, 1);
  216.     setpoint(a, pt, x, y);
  217. }
  218.  
  219. #define S10(x)     ((x) >> SHIFTS)
  220. #define S20(x)     ((x) >> (2*SHIFTS))
  221. #define MUL3(x)  ((x)+((x)<<1))
  222.  
  223. /*
  224.  *  So I can use integer arithmatic, I am defining 512 as 1 (as far
  225.  *  as the mathematics go), which means that I must divide any power
  226.  *  multiplication by 512^(n-1).  E.G. .5^2 = .25 ... to make 256^2
  227.  *  equal 128, I must divide by 512^1
  228.  */
  229.  
  230. drawcurve(a)
  231. register short a[4][2];
  232. {
  233.     long  mr[4];        /* Holds T(t)B partial result    */
  234.     char  lastpt;
  235.     short array[ONE][2];    /* hold points to plot        */
  236.     register long  ttt3, t3, tt3;
  237.     register short t, i, n;
  238.     register long tt, ttt;
  239.  
  240.     lastpt = 0;
  241.     for (t = n = 0; t <= ONE; t += Step) {     /*  t = 0 to 1       */
  242. oncemore:
  243.     tt = t * t;
  244.     ttt= tt * t;
  245.     ttt3 = S20(MUL3(ttt));
  246.     tt3  = S10(MUL3(tt));
  247.     t3   = MUL3(t);
  248.     ttt  = S20(ttt);
  249.  
  250.     mr[0] = -ttt + tt3 - t3 + ONE;
  251.     mr[1] = ttt3 - (tt3<<1) + t3;
  252.     mr[2] = -ttt3 + tt3;
  253.     /* MR[3] is ttt     */
  254.  
  255.     for (i = 0; i < 2; ++i) {
  256.         array[n][i] = (mr[0] * a[0][i] + mr[1] * a[1][i] +
  257.               mr[2] * a[2][i] + ttt * a[3][i]) >> SHIFTS;
  258.     }
  259.     ++n;
  260.     }
  261.     if (lastpt == 0 && t - Step < ONE) {
  262.     lastpt = 1;
  263.     t = ONE;
  264.     goto oncemore;
  265.     }
  266.  
  267.     SetAPen(Rp, 0);
  268.     RectFill(Rp, Ux, Uy, Lx - 1, Ly - 1);
  269.     SetAPen(Rp, 1);
  270.     Move(Rp, a[0][0], a[0][1]);
  271.     PolyDraw(Rp, n, array);
  272.     drawpoints(a, 0, 4);
  273. }
  274.  
  275.  
  276. drawpoints(a, is, ie)
  277. register short a[4][2];
  278. {
  279.     register short i;
  280.     for (i = is; i < ie; ++i) {
  281.     Move(Rp, a[i][0] - 2, a[i][1]);
  282.     Draw(Rp, a[i][0] + 2, a[i][1]);
  283.     Move(Rp, a[i][0], a[i][1] - 2);
  284.     Draw(Rp, a[i][0], a[i][1] + 2);
  285.     }
  286. }
  287.  
  288. /*
  289.  *  AUTO ROUTINES   ------------------------------------------------------
  290.  */
  291.  
  292. loadauto(a, seed)
  293. register short a[4][2];
  294. {
  295.     register short i, j;
  296.     register long n;
  297.     n = random(seed);
  298.     for (i = 0; i < 4; ++i) {
  299.     for (j = 0; j < 2; ++j) {
  300.         n = random(n);
  301.         if ((a[i][j] = (((n>>1) & 15) - 7)) == 0)
  302.         a[i][j] = 1;
  303.     }
  304.     }
  305. }
  306.  
  307. moveauto(au, ar)
  308. register short au[4][2];
  309. register short ar[4][2];
  310. {
  311.     register short i, j;
  312.     short lb[2], mb[2];
  313.  
  314.     lb[0] = Ux; lb[1] = Uy;
  315.     mb[0] = Lx; mb[1] = Ly;
  316.  
  317.     for (i = 0; i < 4; ++i) {
  318.     for (j = 0; j < 2; ++j) {
  319.         if (au[i][j] < 0 && ar[i][j] <= lb[j]+8)
  320.         au[i][j] = -au[i][j];
  321.         if (au[i][j] > 0 && ar[i][j] >= mb[j]-8)
  322.         au[i][j] = -au[i][j];
  323.         ar[i][j] += au[i][j];
  324.     }
  325.     }
  326.     drawcurve(ar);
  327. }
  328.  
  329. random(n)
  330. {
  331.     return((n ^ (n >> 8)) * 13 + 1);
  332. }
  333.  
  334.  
  335. /*
  336.  *  GADGET ROUTINES!    ------------------------------------------------
  337.  */
  338.  
  339.  
  340. #define NG(nn)    &Gadgets[nn+1]
  341. #define G_YGLOB 1
  342. #define G_XGLOB 2
  343.  
  344. XPI Props[] = {
  345.     { AUTOKNOB|FREEVERT , 0, 0, 0x1FFF, 0x1FFF }
  346. };
  347.  
  348. IM Images[] = {
  349.     { 0,0,2,1,1, NULL, 1, 0, NULL },
  350. };
  351.  
  352. GADGET Gadgets[] = {
  353.     {
  354.     NULL, -15, 11, 15, -19, GADGIMAGE|GADGHCOMP|GRELRIGHT|GRELHEIGHT,
  355.     GADGIMMEDIATE|RIGHTBORDER|RELVERIFY,PROPGADGET,
  356.     (APTR)&Images[0],NULL,NULL,0,(APTR)&Props[0], G_YGLOB, 0
  357.     },
  358. };
  359.  
  360. GADGET *Gc;
  361. long GUx, GUy;
  362.  
  363. init_gadgets(nw, ppo)
  364. NW *nw;
  365. XPI **ppo;
  366. {
  367.     nw->FirstGadget = &Gadgets[0];
  368.     *ppo = &Props[0];
  369. }
  370.  
  371.  
  372.