home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * BSPLINE.C
- *
- * Matthew Dillon.
- * Public Domain (no Copyrights whatsoever)
- *
- * -Assumes AZTEC compilation, +L (32 bit ints), with all AMIGA symbols
- * precompiled. Additionally expects certain typedefs and routines
- * found in MY.LIB, as well as some MY.LIB #include files.
- *
- * An experienced programmer can remove the MY.LIB dependancies
- * (openlibs() call), and figure out what typedefs have been assumed if
- * he wishes to compile the program. You can also simply extract the
- * Bezier functions for your own use.
- *
- * BSPLINE EQUATIONS:
- *
- * c(t) = T(t)BP
- *
- * T(t) = (t^3 t^2 t 1) P= ( Pi-1 )
- * B = ( -1 3 -3 1 ) ( Pi )
- * ( 3 -6 3 0 ) ( Pi+1 )
- * ( -3 0 3 0 ) ( Pi+2 )
- * ( 1 4 1 0 )
- *
- * t: range 0 to 1
- * C: coordinate matrix 1xD matrix (D = dimensions)
- * B: Bspline matrix 4x4
- * P: Ctrl. Point matrix 4xD matrix (D = dimensions)
- *
- * using D = 2. For B-Spline, must loop through all control points
- * beginning at Pi+1 and ending at Pend-2
- */
-
- #include <typedefs.h>
- #include <xmisc.h>
-
- #define SHIFTS 9
- #define ONE (1<<SHIFTS)
- #define MAXPTS 256 /* Maximum # of bspline points allowed */
-
- typedef struct PropInfo XPI;
- typedef struct Image IM;
-
- extern IMESS *GetMsg();
-
- #define MYGADGETS (WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE)
-
- NW Nw = {
- 64, 64, 320, 100,
- 0, 1,
- NEWSIZE|MOUSEBUTTONS|MOUSEMOVE|CLOSEWINDOW|GADGETDOWN|GADGETUP|MENUPICK,
- MYGADGETS|REPORTMOUSE|ACTIVATE|NOCAREREFRESH,
- 0, 0, (UBYTE *)"Bspline, By Matthew Dillon", NULL, NULL,
- 32, 64, -1, -1, WBENCHSCREEN
- };
-
- WIN *Win;
- RP *Rp;
- short Ux, Uy, Lx, Ly;
- short Step = 128;
- short Display = 1;
-
- short Pts[MAXPTS+1][2], Npts;
-
- main(ac, av)
- char *av[];
- {
- register IMESS *mess;
- short notdone = 1;
- short pt = -1;
- char mode = 0; /* 0=move pts, 1=add pts, 2=del pts */
-
- short gy, gg = 0;
- XPI *po;
-
- init_gadgets(&Nw, &po);
- exiterr(!openlibs(INTUITION_LIB|GRAPHICS_LIB), "unable to open libs");
- exiterr(!(Win = OpenWindow(&Nw)), "unable to open window");
- init_menu(Win);
- Rp = Win->RPort;
- SetAPen(Rp, 3);
- SetDrMd(Rp, COMPLEMENT);
- setpoint(Pts, 0, 32, 32);
- setpoint(Pts, 1, 40, 40);
- setpoint(Pts, 2, 100, 50);
- setpoint(Pts, 3, 200, 60);
- Npts = 4;
- setbounds(Pts, Npts);
- while (notdone) {
- short mx, my, mm = 0;
- WaitPort(Win->UserPort);
- while (mess = GetMsg(Win->UserPort)) {
- switch(mess->Class) {
- case CLOSEWINDOW:
- notdone = 0;
- break;
- case NEWSIZE:
- setbounds(Pts, Npts);
- break;
- case GADGETUP:
- case GADGETDOWN:
- {
- gg = mess->Class;
- gy = po->VertPot / 256;
- }
- break;
- case MOUSEBUTTONS:
- switch(mess->Code) {
- case SELECTDOWN:
- pt = getpoint(Pts, Npts, mess->MouseX, mess->MouseY);
- switch(mode) {
- case 0:
- mm = 1;
- mx = mess->MouseX;
- my = mess->MouseY;
- goto break2;
- case 1:
- if (pt < 0)
- pt = 0;
- if (Npts != MAXPTS) {
- bmov(Pts[pt], Pts[pt+1], (Npts-pt)*sizeof(Pts[0]));
- Pts[pt][0] = mess->MouseX;
- Pts[pt][1] = mess->MouseY;
- ++Npts;
- }
- break;
- case 2:
- if (pt >= 0 && pt < Npts) {
- bmov(Pts[pt+1], Pts[pt], (Npts-pt)*sizeof(Pts[0]));
- --Npts;
- }
- break;
- }
- clearall();
- drawcurve(Pts, Npts);
- drawpoints(Pts, 0, Npts);
- break;
- case SELECTUP:
- pt = -1;
- break;
- }
- break2:
- break;
- case MENUPICK:
- switch(MENUNUM(mess->Code)) {
- case 0:
- mode = ITEMNUM(mess->Code);
- break;
- case 1:
- drawpoints(Pts, 0, Npts);
- Display = ITEMNUM(mess->Code); /* 0=cross 1=nums */
- drawpoints(Pts, 0, Npts);
- }
- break;
- case MOUSEMOVE:
- if (gg == GADGETDOWN) {
- gy = po->VertPot / 256;
- break;
- }
- if (mode == 0 || mode == 1) {
- mm = 1;
- mx = mess->MouseX;
- my = mess->MouseY;
- }
- break;
- default:
- break;
- }
- ReplyMsg(mess);
- }
- if (mm && pt >= 0) {
- register int i;
- register int n;
-
- i = (pt - 3 < 0) ? 0 : pt - 3;
- n = (i + 7 > Npts) ? Npts - i : 7;
- drawpoints(Pts, pt, pt+1);
- drawcurve(&Pts[i], n);
- setpoint(Pts, pt, mx, my);
- drawcurve(&Pts[i], n);
- drawpoints(Pts, pt, pt+1);
- }
- if (gg) {
- char buf[32];
- if (gg == GADGETUP)
- gg = 0;
- if (gy + 1 >= 0 && gy + 1 != Step) {
- Step = gy + 1;
- sprintf(buf, "gran: %4ld/%ld", Step, ONE);
- clearall();
- drawcurve(Pts, Npts);
- drawpoints(Pts, 0, Npts);
- Move(Rp, Ux + 1, Uy + 16);
- Text(Rp, buf, strlen(buf));
- }
- }
- }
- exiterr(1, NULL);
- }
-
- exiterr(n, str)
- char *str;
- {
- if (n) {
- if (str)
- puts(str);
- if (Win) {
- uninit_menu(Win);
- CloseWindow(Win);
- }
- closelibs(-1);
- exit(1);
- }
- }
-
- setbounds(a, na)
- register long *a;
- {
- Ux = Win->BorderLeft;
- Uy = Win->BorderTop;
- Lx = Win->Width - Win->BorderRight;
- Ly = Win->Height- Win->BorderBottom + 1;
- clearall();
- drawcurve(a, na);
- drawpoints(a, 0, na);
- }
-
- setpoint(a, pt, x, y)
- register short a[4][2];
- {
- a[pt][0] = x;
- a[pt][1] = y;
- }
-
- getpoint(a, na, x, y)
- register short a[][2];
- {
- register short i, bi;
- register long r, br;
-
- for (i = bi = 0, br = 0x7FFFFFFF; i < na; ++i) {
- r = (x-a[i][0])*(x-a[i][0]) + (y-a[i][1])*(y-a[i][1])*3;
- if (r < br) {
- bi = i;
- br = r;
- }
- }
- return(bi);
- }
-
- clearall()
- {
- SetAPen(Rp, 0);
- SetDrMd(Rp, JAM2);
- RectFill(Rp, Ux, Uy, Lx - 1, Ly - 1);
- SetAPen(Rp, 3);
- SetDrMd(Rp, COMPLEMENT);
- }
-
- #define S10(x) ((x) >> SHIFTS)
- #define S20(x) ((x) >> (2*SHIFTS))
-
- /*
- * So I can use integer arithmatic, I am defining 512 as 1 (as far
- * as the mathematics go), which means that I must divide any power
- * multiplication by 512^(n-1). E.G. .5^2 = .25 ... to make 256^2
- * equal 128, I must divide by 512^1
- */
-
- static short Array[ONE+4][2]; /* hold points to plot */
-
- drawcurve(a, na)
- register short a[][2];
- {
- long mr[4];
- register short n, i, t;
- long tt, ttt;
- short last;
-
- for (i = 1; i < na - 2; ++i) {
- for (t = n = last = 0; t <= ONE; t += Step) {
- oncemore:
- tt = t * t;
- ttt= tt* t;
- mr[0] = -S20(ttt/6) + S10(tt/2) - t/2 + ONE/6;
- mr[1] = S20(ttt/2) - S10(tt) + ONE*2/3;
- mr[2] = -S20(ttt/2) + S10(tt/2) + t/2 + ONE/6;
- mr[3] = S20(ttt/6);
-
- Array[n][0] = (mr[0] * a[i-1][0] + mr[1] * a[i][0] + mr[2] * a[i+1][0] + mr[3] * a[i+2][0]) >> SHIFTS;
- Array[n][1] = (mr[0] * a[i-1][1] + mr[1] * a[i][1] + mr[2] * a[i+1][1] + mr[3] * a[i+2][1]) >> SHIFTS;
- if (++n == ONE + 4) {
- --n;
- puts("software error: OVERFLOW");
- }
- }
- if (last == 0 && t > ONE) {
- t = ONE;
- last = 1;
- goto oncemore;
- }
- Move(Rp, Array[0][0], Array[0][1]);
- PolyDraw(Rp, n, Array);
- }
- }
-
-
- drawpoints(a, is, ie)
- register short a[][2];
- {
- register short i;
-
- for (i = is; i < ie; ++i) {
- if (Display) {
- char buf[32];
- Move(Rp, a[i][0], a[i][1]);
- Draw(Rp, a[i][0], a[i][1]);
- Move(Rp, a[i][0] - 16, a[i][1] + 4);
- sprintf(buf, "%ld", i);
- Text(Rp, buf, strlen(buf));
- } else {
- Move(Rp, a[i][0] - 2, a[i][1]);
- Draw(Rp, a[i][0] + 2, a[i][1]);
- Move(Rp, a[i][0], a[i][1] - 2);
- Draw(Rp, a[i][0], a[i][1] + 2);
- }
- }
- }
-
- /*
- * GADGET ROUTINES! ------------------------------------------------
- */
-
-
- #define NG(nn) &Gadgets[nn+1]
- #define G_YGLOB 1
- #define G_XGLOB 2
-
- XPI Props[] = {
- { AUTOKNOB|FREEVERT , 0, 0, 0x1FFF, 0x1FFF }
- };
-
- IM Images[] = {
- { 0,0,2,1,1, NULL, 1, 0, NULL },
- };
-
- GADGET Gadgets[] = {
- {
- NULL, -15, 11, 15, -19, GADGIMAGE|GADGHCOMP|GRELRIGHT|GRELHEIGHT,
- GADGIMMEDIATE|RIGHTBORDER|RELVERIFY,PROPGADGET,
- (APTR)&Images[0],NULL,NULL,0,(APTR)&Props[0], G_YGLOB, 0
- },
- };
-
- GADGET *Gc;
- long GUx, GUy;
-
- init_gadgets(nw, ppo)
- NW *nw;
- XPI **ppo;
- {
- nw->FirstGadget = &Gadgets[0];
- *ppo = &Props[0];
- }
-
- /*
- * MENU ROUTINES! -----------------------------------------------------
- */
-
- ITEXT Itext[] = {
- { 0,1,JAM2,0,0,NULL,(UBYTE *)" Move", NULL },
- { 0,1,JAM2,0,0,NULL,(UBYTE *)" Add", NULL },
- { 0,1,JAM2,0,0,NULL,(UBYTE *)" Delete",NULL },
- { 0,1,JAM2,0,0,NULL,(UBYTE *)" Cross", NULL },
- { 0,1,JAM2,0,0,NULL,(UBYTE *)" Number",NULL }
- };
-
-
- MENUITEM Item0[] = {
- { &Item0[1], 0, 0, 8*11, 8, CHECKIT|ITEMENABLED|COMMSEQ|HIGHCOMP|ITEMTEXT,
- 0xFE, (APTR)&Itext[0], NULL, 'M', NULL, NULL
- },
- {
- &Item0[2], 0, 8, 8*11, 8, CHECKIT|ITEMENABLED|COMMSEQ|HIGHCOMP|ITEMTEXT,
- 0xFD, (APTR)&Itext[1], NULL, 'A', NULL, NULL
- },
- {
- NULL, 0,16, 8*11, 8, CHECKIT|ITEMENABLED|COMMSEQ|HIGHCOMP|ITEMTEXT,
- 0xFB, (APTR)&Itext[2], NULL, 'D', NULL, NULL
- }
- };
-
- MENUITEM Item1[] = {
- { &Item1[1], 0, 0, 8*11, 8, CHECKIT|ITEMENABLED|COMMSEQ|HIGHCOMP|ITEMTEXT,
- 0xFE, (APTR)&Itext[3], NULL, 'C', NULL, NULL
- },
- {
- NULL , 0, 8, 8*11, 8, CHECKIT|ITEMENABLED|COMMSEQ|HIGHCOMP|ITEMTEXT,
- 0xFD, (APTR)&Itext[4], NULL, 'N', NULL, NULL
- }
- };
-
-
- MENU Menu[] = {
- { &Menu[1], 0, 0,8*11, 8, MENUENABLED, "Control", &Item0[0] },
- { NULL , 8*11,0,8*11, 8, MENUENABLED, "Display", &Item1[0] }
- };
-
- init_menu(win)
- WIN *win;
- {
- SetMenuStrip(win, &Menu[0]);
- }
-
- uninit_menu(win)
- WIN *win;
- {
- ClearMenuStrip(win);
- }
-
-
-
-