home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / prog-asm / talincod.lha / talincode.lha / poly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-29  |  10.9 KB  |  459 lines

  1. /* quick point/polygon intersection */
  2.  
  3. #include "exec/types.h"
  4. #include "intuition/intuition.h"
  5.  
  6. #include <macros.h>
  7.  
  8. struct Library *IntuitionBase=NULL, *GfxBase=NULL;
  9. void *OpenLibrary();
  10.  
  11. struct Window *Window=NULL, *OpenWindow();
  12. struct Screen *Screen=NULL, *OpenScreen();
  13. struct ViewPort *vp;                            /* view port */
  14. struct RastPort *rp;                            /* rast port */
  15.  
  16. USHORT colors[8] = { 0x007,0x00C,0xFFF,0x00F,0x407,0xFFF,0x33F,0xF00 };
  17.  
  18. struct NewScreen NewScreen = { 0,0,320,200, 3, 0,1, NULL, CUSTOMSCREEN, };
  19.  
  20. struct NewWindow back_ground =
  21. {    0,0,320,200, 0,1,
  22.     MENUPICK | MOUSEMOVE | MOUSEBUTTONS,
  23.     NOCAREREFRESH | ACTIVATE | SMART_REFRESH | BORDERLESS | REPORTMOUSE,
  24.     NULL,NULL,NULL,NULL,NULL,320,200,320,200,CUSTOMSCREEN,
  25. };
  26.  
  27. #define DF1    ITEMTEXT | ITEMENABLED | HIGHCOMP
  28. #define DF3    ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ
  29. #define DF4    ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ | CHECKIT
  30.  
  31. struct IntuiText
  32.     addp_tx = { 18,1,JAM2,4,1,NULL,(UBYTE *)"Add Points" },
  33.     movp_tx = { 18,1,JAM2,4,1,NULL,(UBYTE *)"Move Points" },
  34.     delp_tx = { 18,1,JAM2,4,1,NULL,(UBYTE *)"Delete Points" };
  35. struct MenuItem
  36.     addp_mi = { NULL    ,0,00,150,10,DF4|CHECKED,0xB,(APTR)&addp_tx,0,'A' },
  37.     movp_mi = { &addp_mi,0,10,150,10,DF4,        0xD,(APTR)&movp_tx,0,'M' },
  38.     delp_mi = { &movp_mi,0,20,150,10,DF4,        0xE,(APTR)&delp_tx,0,'D' };
  39. struct Menu menu2 =
  40.     {    NULL, 100,0,56,10, MENUENABLED | MIDRAWN, "Edit", &delp_mi };
  41.  
  42. struct IntuiText
  43.     abou_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"By David Joiner" },
  44.     svex_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"Save and Exit" },
  45.     quit_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"Exit, No Save" };
  46. struct MenuItem
  47.     abou_mi = { NULL    ,0,00,150,10,DF1,0,(APTR)&abou_tx       },
  48.     svex_mi = { &abou_mi,0,10,150,10,DF3,0,(APTR)&svex_tx,0,'S' },
  49.     quit_mi = { &svex_mi,0,20,150,10,DF3,0,(APTR)&quit_tx,0,'X' };
  50. struct Menu menu1 =
  51.     {    &menu2, 1,0,56,10, MENUENABLED | MIDRAWN, "File", &quit_mi };
  52.  
  53. #define ADD_POINTS        (addp_mi.Flags & CHECKED)
  54. #define MOVE_POINTS        (movp_mi.Flags & CHECKED)
  55. #define DEL_POINTS        (delp_mi.Flags & CHECKED)
  56.  
  57. #define SCAT    goto exit_pgm;
  58.  
  59. struct XY {
  60.     long    x,y;
  61. };
  62.  
  63. #define NUMPOINTS    13
  64.  
  65. struct XY points[] = {
  66.     39,93, 75,51, 61,43, 140,43, 149,55, 176,45, 192,113, 151,74, 118,165,
  67.     98,85, 101,129, 60,156, 47,156
  68. };
  69.  
  70. short editcount = 0, dragpoint = -1;
  71.  
  72. short    delta_x, delta_y;
  73.  
  74. struct XY editpoints[50];
  75.  
  76. main()
  77. {    if ((IntuitionBase = OpenLibrary("intuition.library",0)) == NULL) SCAT;
  78.     if ((GfxBase = OpenLibrary("graphics.library",0)) == NULL) SCAT;
  79.     if ((Screen = OpenScreen(&NewScreen)) == NULL) SCAT;
  80.     vp = &(Screen->ViewPort);
  81.     LoadRGB4(vp,colors,8);
  82.  
  83.     back_ground.Screen = Screen;
  84.     if ((Window = OpenWindow(&back_ground)) == NULL) SCAT;
  85.     rp = Window->RPort;
  86.  
  87.     SetMenuStrip(Window,&menu1);
  88.  
  89.     SetAPen(rp,1);
  90.  
  91.     ptest();
  92.  
  93.     while (TRUE)
  94.     {    ULONG class; USHORT code, length; SHORT mx, my; APTR address;
  95.         struct IntuiMessage *message, *GetMsg();
  96.  
  97.         Wait(1 << Window->UserPort->mp_SigBit);
  98.  
  99.         while (message = GetMsg(Window->UserPort))
  100.         {    class = message->Class;
  101.             code = message->Code;
  102.             address = (APTR)message->IAddress;
  103.             mx = message->MouseX;
  104.             my = message->MouseY;
  105.             ReplyMsg(message);
  106.  
  107.             if (class == MENUPICK)
  108.             {    if (code == MENUNULL) ;
  109.                 else if (MENUNUM(code)==0)
  110.                 {    switch (ITEMNUM(code)) {
  111.                     case 2: break;
  112.                     case 1: break;
  113.                     case 0: SCAT;
  114.                     }
  115.                 }
  116.             }
  117.             else if (class == MOUSEBUTTONS)
  118.             {    if (code == SELECTDOWN)
  119.                 {    if (ADD_POINTS)
  120.                     {    /* number of points is zero, then define a point at
  121.                         the mouse click, and another one dragged by the mouse.
  122.                         If number of points is 1, then add a dragged one at
  123.                         the mouse click.
  124.                         else look for the nearest edge, and "break" it.
  125.                         */
  126.                         if (editcount < 2)
  127.                         {    if (editcount == 0)
  128.                             {    editpoints[0].x = mx;
  129.                                 editpoints[0].y = my;
  130.                             }
  131.                             SetAPen(rp,0);        /* erase existing poly */
  132.                             draw_poly();
  133.                             editpoints[1].x = mx;
  134.                             editpoints[1].y = my;
  135.                             editcount = 2;
  136.                             dragpoint = 1;
  137.                             shadow_poly();
  138.                         }
  139.                         else if (editcount < 50)
  140.                         {    short i, point;
  141.                         /*    point_test(mx,my); */
  142.  
  143.                             point = find_edge(mx,my);
  144.                             if (point >= 0)
  145.                             {    SetAPen(rp,0);        /* erase existing poly */
  146.                                 draw_poly();
  147.                                 for (i= editcount; i>point; i--)
  148.                                     editpoints[i] = editpoints[i-1];
  149.                                 editpoints[point].x = mx;
  150.                                 editpoints[point].y = my;
  151.                                 editcount++;
  152.                                 dragpoint = point;
  153.                                 shadow_poly();
  154.                             }
  155.                         }
  156.                     }
  157.                     else if (MOVE_POINTS)
  158.                     {    short point;
  159.                         /* look for a point to move, mark as a dragger. */
  160.                         if ((point = find_point(mx,my)) >= 0)
  161.                         {    SetAPen(rp,0);        /* erase existing poly */
  162.                             draw_poly();
  163.                             shadow_poly();
  164.                             dragpoint = point;
  165.                         }
  166.                     }
  167.                     else if (DEL_POINTS)
  168.                     {    short point;
  169.  
  170.                         /* look for a point to delete, re-draw */
  171.  
  172.                         if ((point = find_point(mx,my)) >= 0)
  173.                         {    SetAPen(rp,0);        /* erase existing poly */
  174.                             draw_poly();
  175.                             while (point < editcount)
  176.                             {    editpoints[point] = editpoints[point+1];
  177.                                 point++;
  178.                             }
  179.                             editcount--;
  180.                             SetAPen(rp,1);
  181.                             draw_poly();
  182.                         }
  183.                     }
  184.                 }
  185.                 else if (code == SELECTUP)
  186.                 {    if (dragpoint >= 0)
  187.                     {    shadow_poly();
  188.                         dragpoint = -1;
  189.                         SetAPen(rp,1);
  190.                         draw_poly();
  191.                     }
  192.                 }
  193.             }
  194.         }
  195.         if (dragpoint >= 0)
  196.         {    shadow_poly();
  197.             editpoints[dragpoint].x = mx + delta_x;
  198.             editpoints[dragpoint].y = my + delta_y;
  199.             shadow_poly();
  200.         }
  201.     }
  202. exit_pgm:
  203.     if (Window){ ClearMenuStrip(Window); CloseWindow(Window); }
  204.     if (Screen) CloseScreen(Screen);
  205.     if (GfxBase) CloseLibrary(GfxBase);
  206.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  207. }
  208.  
  209. int find_point(x,y) short x,y;
  210. {    short dist = 10, newdist;
  211.     short i, foundpoint = -1;
  212.  
  213.     for (i=0; i<editcount; i++)
  214.     {    newdist = ABS(editpoints[i].x - x) + ABS(editpoints[i].y - y);
  215.  
  216.         if (newdist < dist)
  217.         {    dist = newdist;
  218.             foundpoint = i;
  219.             delta_x = editpoints[i].x - x;
  220.             delta_y = editpoints[i].y - y;
  221.         }
  222.     }
  223.     return foundpoint;
  224. }
  225.  
  226. int find_edge(x,y) short x,y;
  227. {    short    newdist, dist = 10;
  228.     short    foundline = -1, i;
  229.  
  230.     for (i=1; i<editcount; i++)
  231.     {    newdist = line_dist(
  232.             editpoints[i-1].x,editpoints[i-1].y,
  233.             editpoints[i].x,editpoints[i].y,
  234.             x,y);
  235.  
  236.         if (newdist < dist)
  237.         {    dist = newdist;
  238.             foundline = i;
  239.         }
  240.     }
  241.  
  242.     newdist = line_dist(
  243.         editpoints[0].x,editpoints[0].y,
  244.         editpoints[editcount-1].x,editpoints[editcount-1].y,
  245.         x,y);
  246.  
  247.     if (newdist < dist)
  248.     {    dist = newdist;
  249.         foundline = 0;
  250.     }
  251.     return foundline;
  252. }
  253.  
  254. shadow_poly()
  255. {    SetDrMd(rp,COMPLEMENT);
  256.     draw_poly();
  257.     SetDrMd(rp,JAM1);
  258. }
  259.  
  260. draw_poly()
  261. {    short i;
  262.  
  263.     Move(rp,editpoints[0].x,editpoints[0].y);
  264.  
  265.     for (i=1; i<editcount; i++)
  266.         Draw(rp,editpoints[i].x,editpoints[i].y);
  267.  
  268.     /* the condition allows us to not re-draw the same line when there is
  269.         only 2 points. */
  270.  
  271.     if (editcount != 2) Draw(rp,editpoints[0].x,editpoints[0].y);
  272. }
  273.  
  274. #if 0
  275. point_test(x3,y3) short x3,y3;
  276. {    short    x1 = editpoints[0].x,
  277.             y1 = editpoints[0].y,
  278.             x2 = editpoints[1].x,
  279.             y2 = editpoints[1].y;
  280.     long    x,y;
  281.  
  282.     short    a,b;
  283.  
  284.     long    aa,bb,ab;
  285.  
  286.     a = x2 - x1;
  287.     b = y2 - y1;
  288.  
  289.     aa = a*a;
  290.     bb = b*b;
  291.     ab = a*b;
  292.  
  293.     x = (bb * x1 + aa * x3 + ab * (y3-y1)) / (bb+aa);
  294.     y = (aa * y1 + bb * y3 + ab * (x3-x1)) / (bb+aa);
  295. }
  296. #endif
  297.  
  298. line_dist(x1,y1,x2,y2,mx,my) short x1,y1,x2,y2,mx,my;
  299. {    long    x,y,t;
  300.  
  301.     short    a,b;
  302.  
  303.     long    aa,bb,ab;
  304.  
  305.     a = x2 - x1;
  306.     b = y2 - y1;
  307.  
  308.     aa = a*a;
  309.     bb = b*b;
  310.     ab = a*b;
  311.  
  312.     x = (bb * x1 + aa * mx + ab * (my-y1)) / (bb+aa);
  313.     y = (aa * y1 + bb * my + ab * (mx-x1)) / (bb+aa);
  314.  
  315.     if (x1 > x2) { t = x1; x1 = x2; x2 = t; }
  316.     if (mx < x1 || mx > x2) return 100;
  317.  
  318.     if (y1 > y2) { t = y1; y1 = y2; y2 = t; }
  319.     if (my < y1 || my > y2) return 100;
  320.  
  321.     return ABS(mx-x) + ABS(my-y);
  322. }
  323.  
  324. ptest()
  325. {    short i, x, y;
  326.  
  327.     Move(rp,points[0].x,points[0].y);
  328.  
  329.     for (i=0; i<NUMPOINTS-1; i++)
  330.         Draw(rp,points[i+1].x,points[i+1].y);
  331.  
  332.     Draw(rp,points[0].x,points[0].y);
  333.  
  334.     for (x=35; x<200; x++)
  335.     {    for (y=40; y<170; y++)
  336.         {    if (point_in_poly(x,y))
  337.                 pixel(rp->BitMap,x,y,2);
  338.         }
  339.     }
  340. }
  341.  
  342. point_in_poly(x,y) long x,y;
  343. {    short            lleft=0;                /* lines to the left */
  344.     register short    i,
  345.                     px,py,                    /* current point */
  346.                     ox,oy;                    /* previous point */
  347.  
  348.     /* we need to know if the point is to the left of an even number of lines. */
  349.  
  350.     i=0;                                    /* start at 0th vertex */
  351.     px = points[0].x;                        /* get current point */
  352.     py = points[0].y;
  353.  
  354.     if (py > y) goto startbelow;            /* if below line then start below */
  355.     /* Q: If we start on a horizontal line, what happens? */
  356.  
  357. startabove:
  358.     ox = px;                                /* set old point to current */
  359.     oy = py;
  360.     i++;                                    /* next vertex */
  361.     if (i < NUMPOINTS)                        /* if not last edge */
  362.     {    px = points[i].x;                    /* get new vertex */
  363.         py = points[i].y;
  364.     }
  365.     else if (i == NUMPOINTS)                /* if last edge */
  366.     {    px = points[0].x;                    /* use first vertex */
  367.         py = points[0].y;
  368.     }
  369.     else return lleft;                        /* else if done, return */
  370.  
  371.     if (py <= y) goto startabove;            /* if still above, then loop */
  372.  
  373.     if (px < x)                                /* if new point to the left */
  374.     {    if (ox < x) lleft = !lleft;            /* and old one too, then mark */
  375.         else                                /* else within bounding box, do slope */
  376.             if ( (px - ox)*(y - oy) < (py - oy)*(x - ox) ) lleft = !lleft;
  377.     }
  378.     else
  379.     {    if ((ox < x) &&                        /* else if within bound box, slope calc */
  380.             (px - ox)*(y - oy) < (py - oy)*(x - ox) ) lleft = !lleft;
  381.     }
  382. /*    goto startbelow;    */                    /* next line starts below point */
  383.  
  384. startbelow:
  385.     ox = px;                                /* set old point to current */
  386.     oy = py;
  387.     i++;                                    /* next vertex */
  388.     if (i < NUMPOINTS)                        /* if not last edge */
  389.     {    px = points[i].x;                    /* get new vertex */
  390.         py = points[i].y;
  391.     }
  392.     else if (i == NUMPOINTS)                /* if last edge */
  393.     {    px = points[0].x;                    /* use first vertex */
  394.         py = points[0].y;
  395.     }
  396.     else return lleft;                        /* else if done, return */
  397.  
  398.     if (py > y) goto startbelow;            /* if still below, then loop */
  399.  
  400.     if (px < x)                                /* if new point to the left */
  401.     {    if (ox < x) lleft = !lleft;            /* and old one, then it's left */
  402.         else                                /* else it's in bounds, do slope calc */
  403.             if ( (px - ox)*(y - oy) > (py - oy)*(x - ox) ) lleft = !lleft;
  404.     }
  405.     else        /* if it's in the bounds, do slope calc */
  406.     {    if (ox < x && (px - ox)*(y - oy) > (py - oy)*(x - ox) ) lleft = !lleft;
  407.     }
  408.     goto startabove;
  409. }
  410.  
  411. #asm
  412.  
  413. ; pixel(bitmap,x,y,color); - parameters at 4, 8, 12, 16
  414.  
  415. BMWidth            equ    0        ; bit map width
  416. BMRows            equ    2        ; bit map height
  417. BMFlags            equ    4        ; bit map flags
  418. BMDepth            equ    5        ; bit map depth
  419. BMPlanes        equ    8        ; bit map planes
  420.  
  421. BMAP            equ    4        ; bit map param
  422. XC                equ    8+2
  423. YC                equ    12+2
  424. COLOR            equ    16+2
  425.  
  426.         public    _pixel
  427. _pixel
  428.         move.l    BMAP(sp),a0            ; address of bit map
  429.         move.w    YC(sp),d1            ; y coord (word)
  430.  
  431.         mulu.w    BMWidth(a0),d1        ; y * width in bytes
  432.         move.w    XC(sp),d0            ; x coord
  433.         lsr.w    #3,d0                ; x / 8
  434.         add.w    d0,d1
  435.  
  436.         move.w    XC(sp),d0            ; x coord
  437.         not.w    d0
  438.         and.w    #7,d0                ; x & 7 = x mod 8
  439.         move.w    COLOR(sp),d2        ; color
  440.  
  441.         clr.w    d3                    ; clear upper byte of low word
  442.         move.b    BMDepth(a0),d3        ; do (depth) times
  443.         lea        BMPlanes(a0),a0
  444.         bra        3$
  445.  
  446. 1$        move.l    (a0)+,a1            ; get nth bit plane address
  447.         lsr.w    #1,d2                ; shift color by 1 bit
  448.         bcc.s    2$
  449.  
  450.         bset    d0,(a1,d1.w)        ; set the bit
  451.         dbra    d3,1$
  452.         rts
  453.  
  454. 2$        bclr    d0,(a1,d1.w)        ; clear the bit
  455. 3$        dbra    d3,1$
  456.         rts
  457.  
  458. #endasm
  459.