home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 038.lha / Bezier.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-05-16  |  7.8 KB  |  389 lines

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