home *** CD-ROM | disk | FTP | other *** search
- /* quick point/polygon intersection */
-
- #include "exec/types.h"
- #include "intuition/intuition.h"
-
- #include <macros.h>
-
- struct Library *IntuitionBase=NULL, *GfxBase=NULL;
- void *OpenLibrary();
-
- struct Window *Window=NULL, *OpenWindow();
- struct Screen *Screen=NULL, *OpenScreen();
- struct ViewPort *vp; /* view port */
- struct RastPort *rp; /* rast port */
-
- USHORT colors[8] = { 0x007,0x00C,0xFFF,0x00F,0x407,0xFFF,0x33F,0xF00 };
-
- struct NewScreen NewScreen = { 0,0,320,200, 3, 0,1, NULL, CUSTOMSCREEN, };
-
- struct NewWindow back_ground =
- { 0,0,320,200, 0,1,
- MENUPICK | MOUSEMOVE | MOUSEBUTTONS,
- NOCAREREFRESH | ACTIVATE | SMART_REFRESH | BORDERLESS | REPORTMOUSE,
- NULL,NULL,NULL,NULL,NULL,320,200,320,200,CUSTOMSCREEN,
- };
-
- #define DF1 ITEMTEXT | ITEMENABLED | HIGHCOMP
- #define DF3 ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ
- #define DF4 ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ | CHECKIT
-
- struct IntuiText
- addp_tx = { 18,1,JAM2,4,1,NULL,(UBYTE *)"Add Points" },
- movp_tx = { 18,1,JAM2,4,1,NULL,(UBYTE *)"Move Points" },
- delp_tx = { 18,1,JAM2,4,1,NULL,(UBYTE *)"Delete Points" };
- struct MenuItem
- addp_mi = { NULL ,0,00,150,10,DF4|CHECKED,0xB,(APTR)&addp_tx,0,'A' },
- movp_mi = { &addp_mi,0,10,150,10,DF4, 0xD,(APTR)&movp_tx,0,'M' },
- delp_mi = { &movp_mi,0,20,150,10,DF4, 0xE,(APTR)&delp_tx,0,'D' };
- struct Menu menu2 =
- { NULL, 100,0,56,10, MENUENABLED | MIDRAWN, "Edit", &delp_mi };
-
- struct IntuiText
- abou_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"By David Joiner" },
- svex_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"Save and Exit" },
- quit_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"Exit, No Save" };
- struct MenuItem
- abou_mi = { NULL ,0,00,150,10,DF1,0,(APTR)&abou_tx },
- svex_mi = { &abou_mi,0,10,150,10,DF3,0,(APTR)&svex_tx,0,'S' },
- quit_mi = { &svex_mi,0,20,150,10,DF3,0,(APTR)&quit_tx,0,'X' };
- struct Menu menu1 =
- { &menu2, 1,0,56,10, MENUENABLED | MIDRAWN, "File", &quit_mi };
-
- #define ADD_POINTS (addp_mi.Flags & CHECKED)
- #define MOVE_POINTS (movp_mi.Flags & CHECKED)
- #define DEL_POINTS (delp_mi.Flags & CHECKED)
-
- #define SCAT goto exit_pgm;
-
- struct XY {
- long x,y;
- };
-
- #define NUMPOINTS 13
-
- struct XY points[] = {
- 39,93, 75,51, 61,43, 140,43, 149,55, 176,45, 192,113, 151,74, 118,165,
- 98,85, 101,129, 60,156, 47,156
- };
-
- short editcount = 0, dragpoint = -1;
-
- short delta_x, delta_y;
-
- struct XY editpoints[50];
-
- main()
- { if ((IntuitionBase = OpenLibrary("intuition.library",0)) == NULL) SCAT;
- if ((GfxBase = OpenLibrary("graphics.library",0)) == NULL) SCAT;
- if ((Screen = OpenScreen(&NewScreen)) == NULL) SCAT;
- vp = &(Screen->ViewPort);
- LoadRGB4(vp,colors,8);
-
- back_ground.Screen = Screen;
- if ((Window = OpenWindow(&back_ground)) == NULL) SCAT;
- rp = Window->RPort;
-
- SetMenuStrip(Window,&menu1);
-
- SetAPen(rp,1);
-
- ptest();
-
- while (TRUE)
- { ULONG class; USHORT code, length; SHORT mx, my; APTR address;
- struct IntuiMessage *message, *GetMsg();
-
- Wait(1 << Window->UserPort->mp_SigBit);
-
- while (message = GetMsg(Window->UserPort))
- { class = message->Class;
- code = message->Code;
- address = (APTR)message->IAddress;
- mx = message->MouseX;
- my = message->MouseY;
- ReplyMsg(message);
-
- if (class == MENUPICK)
- { if (code == MENUNULL) ;
- else if (MENUNUM(code)==0)
- { switch (ITEMNUM(code)) {
- case 2: break;
- case 1: break;
- case 0: SCAT;
- }
- }
- }
- else if (class == MOUSEBUTTONS)
- { if (code == SELECTDOWN)
- { if (ADD_POINTS)
- { /* number of points is zero, then define a point at
- the mouse click, and another one dragged by the mouse.
- If number of points is 1, then add a dragged one at
- the mouse click.
- else look for the nearest edge, and "break" it.
- */
- if (editcount < 2)
- { if (editcount == 0)
- { editpoints[0].x = mx;
- editpoints[0].y = my;
- }
- SetAPen(rp,0); /* erase existing poly */
- draw_poly();
- editpoints[1].x = mx;
- editpoints[1].y = my;
- editcount = 2;
- dragpoint = 1;
- shadow_poly();
- }
- else if (editcount < 50)
- { short i, point;
- /* point_test(mx,my); */
-
- point = find_edge(mx,my);
- if (point >= 0)
- { SetAPen(rp,0); /* erase existing poly */
- draw_poly();
- for (i= editcount; i>point; i--)
- editpoints[i] = editpoints[i-1];
- editpoints[point].x = mx;
- editpoints[point].y = my;
- editcount++;
- dragpoint = point;
- shadow_poly();
- }
- }
- }
- else if (MOVE_POINTS)
- { short point;
- /* look for a point to move, mark as a dragger. */
- if ((point = find_point(mx,my)) >= 0)
- { SetAPen(rp,0); /* erase existing poly */
- draw_poly();
- shadow_poly();
- dragpoint = point;
- }
- }
- else if (DEL_POINTS)
- { short point;
-
- /* look for a point to delete, re-draw */
-
- if ((point = find_point(mx,my)) >= 0)
- { SetAPen(rp,0); /* erase existing poly */
- draw_poly();
- while (point < editcount)
- { editpoints[point] = editpoints[point+1];
- point++;
- }
- editcount--;
- SetAPen(rp,1);
- draw_poly();
- }
- }
- }
- else if (code == SELECTUP)
- { if (dragpoint >= 0)
- { shadow_poly();
- dragpoint = -1;
- SetAPen(rp,1);
- draw_poly();
- }
- }
- }
- }
- if (dragpoint >= 0)
- { shadow_poly();
- editpoints[dragpoint].x = mx + delta_x;
- editpoints[dragpoint].y = my + delta_y;
- shadow_poly();
- }
- }
- exit_pgm:
- if (Window){ ClearMenuStrip(Window); CloseWindow(Window); }
- if (Screen) CloseScreen(Screen);
- if (GfxBase) CloseLibrary(GfxBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
- }
-
- int find_point(x,y) short x,y;
- { short dist = 10, newdist;
- short i, foundpoint = -1;
-
- for (i=0; i<editcount; i++)
- { newdist = ABS(editpoints[i].x - x) + ABS(editpoints[i].y - y);
-
- if (newdist < dist)
- { dist = newdist;
- foundpoint = i;
- delta_x = editpoints[i].x - x;
- delta_y = editpoints[i].y - y;
- }
- }
- return foundpoint;
- }
-
- int find_edge(x,y) short x,y;
- { short newdist, dist = 10;
- short foundline = -1, i;
-
- for (i=1; i<editcount; i++)
- { newdist = line_dist(
- editpoints[i-1].x,editpoints[i-1].y,
- editpoints[i].x,editpoints[i].y,
- x,y);
-
- if (newdist < dist)
- { dist = newdist;
- foundline = i;
- }
- }
-
- newdist = line_dist(
- editpoints[0].x,editpoints[0].y,
- editpoints[editcount-1].x,editpoints[editcount-1].y,
- x,y);
-
- if (newdist < dist)
- { dist = newdist;
- foundline = 0;
- }
- return foundline;
- }
-
- shadow_poly()
- { SetDrMd(rp,COMPLEMENT);
- draw_poly();
- SetDrMd(rp,JAM1);
- }
-
- draw_poly()
- { short i;
-
- Move(rp,editpoints[0].x,editpoints[0].y);
-
- for (i=1; i<editcount; i++)
- Draw(rp,editpoints[i].x,editpoints[i].y);
-
- /* the condition allows us to not re-draw the same line when there is
- only 2 points. */
-
- if (editcount != 2) Draw(rp,editpoints[0].x,editpoints[0].y);
- }
-
- #if 0
- point_test(x3,y3) short x3,y3;
- { short x1 = editpoints[0].x,
- y1 = editpoints[0].y,
- x2 = editpoints[1].x,
- y2 = editpoints[1].y;
- long x,y;
-
- short a,b;
-
- long aa,bb,ab;
-
- a = x2 - x1;
- b = y2 - y1;
-
- aa = a*a;
- bb = b*b;
- ab = a*b;
-
- x = (bb * x1 + aa * x3 + ab * (y3-y1)) / (bb+aa);
- y = (aa * y1 + bb * y3 + ab * (x3-x1)) / (bb+aa);
- }
- #endif
-
- line_dist(x1,y1,x2,y2,mx,my) short x1,y1,x2,y2,mx,my;
- { long x,y,t;
-
- short a,b;
-
- long aa,bb,ab;
-
- a = x2 - x1;
- b = y2 - y1;
-
- aa = a*a;
- bb = b*b;
- ab = a*b;
-
- x = (bb * x1 + aa * mx + ab * (my-y1)) / (bb+aa);
- y = (aa * y1 + bb * my + ab * (mx-x1)) / (bb+aa);
-
- if (x1 > x2) { t = x1; x1 = x2; x2 = t; }
- if (mx < x1 || mx > x2) return 100;
-
- if (y1 > y2) { t = y1; y1 = y2; y2 = t; }
- if (my < y1 || my > y2) return 100;
-
- return ABS(mx-x) + ABS(my-y);
- }
-
- ptest()
- { short i, x, y;
-
- Move(rp,points[0].x,points[0].y);
-
- for (i=0; i<NUMPOINTS-1; i++)
- Draw(rp,points[i+1].x,points[i+1].y);
-
- Draw(rp,points[0].x,points[0].y);
-
- for (x=35; x<200; x++)
- { for (y=40; y<170; y++)
- { if (point_in_poly(x,y))
- pixel(rp->BitMap,x,y,2);
- }
- }
- }
-
- point_in_poly(x,y) long x,y;
- { short lleft=0; /* lines to the left */
- register short i,
- px,py, /* current point */
- ox,oy; /* previous point */
-
- /* we need to know if the point is to the left of an even number of lines. */
-
- i=0; /* start at 0th vertex */
- px = points[0].x; /* get current point */
- py = points[0].y;
-
- if (py > y) goto startbelow; /* if below line then start below */
- /* Q: If we start on a horizontal line, what happens? */
-
- startabove:
- ox = px; /* set old point to current */
- oy = py;
- i++; /* next vertex */
- if (i < NUMPOINTS) /* if not last edge */
- { px = points[i].x; /* get new vertex */
- py = points[i].y;
- }
- else if (i == NUMPOINTS) /* if last edge */
- { px = points[0].x; /* use first vertex */
- py = points[0].y;
- }
- else return lleft; /* else if done, return */
-
- if (py <= y) goto startabove; /* if still above, then loop */
-
- if (px < x) /* if new point to the left */
- { if (ox < x) lleft = !lleft; /* and old one too, then mark */
- else /* else within bounding box, do slope */
- if ( (px - ox)*(y - oy) < (py - oy)*(x - ox) ) lleft = !lleft;
- }
- else
- { if ((ox < x) && /* else if within bound box, slope calc */
- (px - ox)*(y - oy) < (py - oy)*(x - ox) ) lleft = !lleft;
- }
- /* goto startbelow; */ /* next line starts below point */
-
- startbelow:
- ox = px; /* set old point to current */
- oy = py;
- i++; /* next vertex */
- if (i < NUMPOINTS) /* if not last edge */
- { px = points[i].x; /* get new vertex */
- py = points[i].y;
- }
- else if (i == NUMPOINTS) /* if last edge */
- { px = points[0].x; /* use first vertex */
- py = points[0].y;
- }
- else return lleft; /* else if done, return */
-
- if (py > y) goto startbelow; /* if still below, then loop */
-
- if (px < x) /* if new point to the left */
- { if (ox < x) lleft = !lleft; /* and old one, then it's left */
- else /* else it's in bounds, do slope calc */
- if ( (px - ox)*(y - oy) > (py - oy)*(x - ox) ) lleft = !lleft;
- }
- else /* if it's in the bounds, do slope calc */
- { if (ox < x && (px - ox)*(y - oy) > (py - oy)*(x - ox) ) lleft = !lleft;
- }
- goto startabove;
- }
-
- #asm
-
- ; pixel(bitmap,x,y,color); - parameters at 4, 8, 12, 16
-
- BMWidth equ 0 ; bit map width
- BMRows equ 2 ; bit map height
- BMFlags equ 4 ; bit map flags
- BMDepth equ 5 ; bit map depth
- BMPlanes equ 8 ; bit map planes
-
- BMAP equ 4 ; bit map param
- XC equ 8+2
- YC equ 12+2
- COLOR equ 16+2
-
- public _pixel
- _pixel
- move.l BMAP(sp),a0 ; address of bit map
- move.w YC(sp),d1 ; y coord (word)
-
- mulu.w BMWidth(a0),d1 ; y * width in bytes
- move.w XC(sp),d0 ; x coord
- lsr.w #3,d0 ; x / 8
- add.w d0,d1
-
- move.w XC(sp),d0 ; x coord
- not.w d0
- and.w #7,d0 ; x & 7 = x mod 8
- move.w COLOR(sp),d2 ; color
-
- clr.w d3 ; clear upper byte of low word
- move.b BMDepth(a0),d3 ; do (depth) times
- lea BMPlanes(a0),a0
- bra 3$
-
- 1$ move.l (a0)+,a1 ; get nth bit plane address
- lsr.w #1,d2 ; shift color by 1 bit
- bcc.s 2$
-
- bset d0,(a1,d1.w) ; set the bit
- dbra d3,1$
- rts
-
- 2$ bclr d0,(a1,d1.w) ; clear the bit
- 3$ dbra d3,1$
- rts
-
- #endasm
-