home *** CD-ROM | disk | FTP | other *** search
/ Phoenix Heaven Sunny 2 / APPARE2.BIN / oh_towns / art2 / src.lzh / SUBGRP.C < prev    next >
C/C++ Source or Header  |  1995-06-18  |  11KB  |  470 lines

  1. /*
  2.  
  3. 描画アルゴリズム
  4.  
  5. void do_line_cont(int x1,int y1,int x2,int y2,void func(int x,int y)!)
  6. void do_line(int x1,int y1,int x2,int y2,void func(int x,int y)!)
  7.  
  8. do_paint
  9. void do_blot(int x, int y, int branch, int depth,
  10.              void pset(int x,int y,int gray)!)
  11. void do_polygon(POINT* points, int nPoint, void hline(int x1,int x2,int y)!)
  12.  
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <winb.h>
  19. #include <te.h>
  20. #include <fntb.h>
  21. #include <gui.h>
  22. #include <egb.h>
  23. #include <wgb.h>
  24. #include <msdos.cf>
  25. #include "art.h"
  26. #include "guisub.h"
  27. #include "wgbmac.H"
  28.  
  29. #include "subgrp.h"
  30. #include "imath.h"
  31.  
  32. #define swap(a,b)  { int t; t=(a); (a)=(b); (b)=t; }
  33.  
  34.  
  35. /*--------------------------------------------------------*/
  36. /*                    描画アルゴリズム                    */
  37. /*--------------------------------------------------------*/
  38.  
  39. void do_line_cont(int x1,int y1,int x2,int y2,void func(int x,int y)!)
  40. {
  41.     int xr,yr,r,x,y;
  42.     xr=abs(x2-x1),yr=abs(y2-y1);
  43.     if (xr==0 && yr==0)
  44.         ;
  45.     else if (xr > yr)
  46.     {
  47.         r=(yr<<16)/xr; if(y1>y2) r=-r;
  48.         if (x1 < x2)
  49.             for (x=x1+1,y=(y1<<16)+0x8000+r; x<=x2; x++,y+=r)
  50.                 func(x,(y>>16));
  51.         else 
  52.             for (x=x1-1,y=(y1<<16)+0x8000+r; x>=x2; x--,y+=r)
  53.                 func(x,(y>>16));
  54.     }
  55.     else
  56.     {
  57.         r=(xr<<16)/yr; if(x1>x2) r=-r;
  58.         if (y1 < y2)
  59.             for (y=y1+1,x=(x1<<16)+0x8000+r; y<=y2; y++,x+=r)
  60.                 func((x>>16),y);
  61.         else
  62.             for (y=y1-1,x=(x1<<16)+0x8000+r; y>=y2; y--,x+=r)
  63.                 func((x>>16),y);
  64.     }
  65. }
  66.  
  67. void do_line(int x1,int y1,int x2,int y2,void func(int x,int y)!)
  68. {
  69.     func(x1,y1);    // 最初の点
  70.     do_line_cont(x1,y1,x2,y2,func);
  71. }
  72.  
  73. void do_boxline(int x1,int y1,int x2,int y2,void func(int x,int y)!)
  74. {
  75.     int i;
  76.     if (x2<x1) swap(x1,x2);
  77.     if (y2<y1) swap(y1,y2);
  78.     for(i=x1;i<=x2;i++) func(i,y1);
  79.     if(y1<y2)
  80.         for(i=x1;i<=x2;i++) func(i,y2);
  81.     for(i=y1+1;i<y2;i++) func(x1,i);
  82.     if(x1<x2)
  83.         for(i=y1+1;i<y2;i++) func(x2,i);
  84. }
  85.  
  86. void do_boxfill(int x1,int y1,int x2,int y2,void func(int x1,int x2,int y)!)
  87. {
  88.     int i;
  89.     if (x2<x1) swap(x1,x2);
  90.     if (y2<y1) swap(y1,y2);
  91.     for(i=y1;i<=y2;i++) func(x1,x2,i);
  92. }
  93.  
  94. void do_ellipse(int x,int y,int rx,int ry,void func(int x,int y)!)
  95. {
  96. #if 0
  97.     #define    ELLIPSE(RX,RY,X0,Y0,X1,Y1)                            \
  98.         {                                                        \
  99.             int x0=RX,s=x0;                                        \
  100.             int y0=0;                                            \
  101.             int px0=-1,py0=-1,px1=-1,py1=-1;                    \
  102.             while(x0>=y0)                                        \
  103.             {                                                    \
  104.                 int x1=x0*RY/RX;                        \
  105.                 int y1=y0*RY/RX;                        \
  106.                 if(px0!=X0||py1!=Y1)                    \
  107.                 {                                                    \
  108.                     func(x+X0,y+Y1);if(X0!=0)func(x-X0,y+Y1);        \
  109.                     if (Y1!=0)                                        \
  110.                      { func(x+X0,y-Y1);if(X0!=0)func(x-X0,y-Y1); }    \
  111.                 }                                                    \
  112.                 if (py0!=Y0||px1!=X1)                                \
  113.                 {                                                \
  114.                     func(x+Y0,y+X1);if(Y0!=0)func(x-Y0,y+X1);        \
  115.                     if (X1!=0)                                        \
  116.                      { func(x+Y0,y-X1);if(Y0!=0)func(x-Y0,y-X1); }    \
  117.                 }                                                \
  118.                 s-=2*y0+1; if(s<0)s+=2*(x0-1),x0--;                \
  119.                 y0++;                                            \
  120.                 px0=X0,py0=Y0,px1=X1,py1=Y1;                    \
  121.             }                                                    \
  122.         }
  123.     #
  124.     if (rx==0 && ry==0)
  125.         func(x,y);
  126.     else if (rx>ry)
  127.         ELLIPSE(rx,ry,x0,y0,x1,y1)
  128.     else
  129.         ELLIPSE(ry,rx,x1,y1,x0,y0)
  130.     #undef ELLIPSE
  131. #endif
  132.     if (rx==0 && ry==0)
  133.         { func(x,y); return; }
  134.     int px,py,prey;
  135.     int a2,b2;
  136.     int c1,c2;
  137.     int e;
  138.     a2=rx*rx,b2=ry*ry;
  139.     px=0,py=ry;
  140.     c1=4*b2,c2=8*a2;
  141.     e=a2*(1-4*ry);
  142.     while(b2*px<=a2*py)
  143.     {
  144.         func(x+px,y+py); if(px!=0)func(x-px,y+py);
  145.         func(x+px,y-py); if(px!=0)func(x-px,y-py);
  146.         prey=py;
  147.         e+=c1*(2*px+1),px++; if(e>0) e-=c2*py,py--;
  148.     }
  149.     px=rx,py=0;
  150.     c1=4*a2,c2=8*b2;
  151.     e=b2*(1-4*rx);
  152.     while(a2*py<=b2*px && py<prey)
  153.     {
  154.         func(x+px,y+py); if(px!=0)func(x-px,y+py);
  155.         if(py!=0) { func(x+px,y-py); if(px!=0)func(x-px,y-py); }
  156.         e+=c1*(2*py+1),py++; if(e>0) e-=c2*px,px--;
  157.     }
  158. }
  159.  
  160. void do_ellipsefill(int x,int y,int rx,int ry,void func(int x1,int x2,int y)!)
  161. {
  162. #if 0
  163.     #define    ELLIPSE(RX,RY,X0,Y0,X1,Y1)                    \
  164.         {                                                \
  165.             int x0=RX,s=x0;                                \
  166.             int y0=0;                                    \
  167.             int py0,py1;                                \
  168.             py0=py1=INT_MIN;                            \
  169.             while(x0>=y0)                                \
  170.             {                                            \
  171.                 int x1=x0*RY/RX;                        \
  172.                 int y1=y0*RY/RX;                        \
  173.                 if (y+Y1 != py0)                        \
  174.                 {                                        \
  175.                     py0=y+Y1;                            \
  176.                     func(x-X0,x+X0,py0);                \
  177.                     func(x-X0,x+X0,y-Y1);                \
  178.                 }                                        \
  179.                 if (y+X1 != py1)                        \
  180.                 {                                        \
  181.                     py1=y+X1;                            \
  182.                     func(x-Y0,x+Y0,py1);                \
  183.                     func(x-Y0,x+Y0,y-X1);                \
  184.                 }                                        \
  185.                 s-=2*y0-1; if(s<0)s+=2*(x0-1),x0--;        \
  186.                 y0++;                                    \
  187.             }                                            \
  188.         }
  189.     #
  190.     if (rx==0&&ry==0)
  191.         func(x,x,y);
  192.     else if (rx>ry)
  193.         ELLIPSE(rx,ry,x0,y0,x1,y1)
  194.     else
  195.         ELLIPSE(ry,rx,x1,y1,x0,y0)
  196.     #undef ELLIPSE
  197. #endif
  198.     if (rx==0 && ry==0)
  199.         { func(x,x,y); return; }
  200.     int px,py,prey;
  201.     int a2,b2;
  202.     int c1,c2;
  203.     int e;
  204.     a2=rx*rx,b2=ry*ry;
  205.     px=0,py=ry;
  206.     c1=4*b2,c2=8*a2;
  207.     e=a2*(1-4*ry);
  208.     prey=-1;
  209.     while(b2*px<=a2*py)
  210.     {
  211.         e+=c1*(2*px+1);
  212.         if(e>0)
  213.         {
  214.             func(x-px,x+px,y+py); func(x-px,x+px,y-py);
  215.             prey=py;
  216.              e-=c2*py,py--;
  217.         }
  218.         px++;
  219.     }
  220.     px=rx,py=0;
  221.     c1=4*a2,c2=8*b2;
  222.     e=b2*(1-4*rx);
  223.     while(a2*py<=b2*px && py<prey)
  224.     {
  225.         func(x-px,x+px,y+py);
  226.         if(py!=0) func(x-px,x+px,y-py);
  227.         e+=c1*(2*py+1),py++; if(e>0) e-=c2*px,px--;
  228.     }
  229. }
  230.  
  231. /*--------------------------------------------------------*/
  232. /*                    ペイントルーチン                    */
  233. /*--------------------------------------------------------*/
  234.  
  235. typedef struct {
  236.     short int  x,y;
  237.     short int  px1,px2,py;
  238.     BOOL mark;
  239. } STACK;
  240.  
  241. void do_paint(int x,int y, int picwid, int picht,
  242.               void hline(int x1,int x2,int y)!,
  243.               BOOL shouldPaint(int x,int y)!,    // point(x,y) == border
  244.               int srchleft(int x,int y)!,
  245.               int srchright(int x,int y)!)
  246. {
  247.     #define STACKSIZE 600
  248.   // ラスタリージョンの追加を行う関数
  249.     STACK *check(int px1,int px2,int py,int sx1,int sx2,int sy,
  250.                  int y, STACK *stack,int stacksize, STACK *sp)
  251.         // 新しい sp を返す
  252.     {
  253.         int x;
  254.         BOOL in_border;
  255.         if (y<0 || picht<=y)
  256.             return sp;
  257.         in_border = TRUE;
  258.         for (x=sx1; x<=sx2; x++) {
  259.             if (in_border) {
  260.                 if (shouldPaint(x,y)) {
  261.                     if (!(y==py&&px1<=x&&x<=px2) && sp+1 < stack+stacksize) {
  262.                         sp++;
  263.                         sp->x = x;
  264.                         sp->y = y;
  265.                         sp->px1 = sx1;
  266.                         sp->px2 = sx2;
  267.                         sp->py = sy;
  268.                         sp->mark = TRUE;
  269.                     }
  270.                     in_border = FALSE;
  271.                 }
  272.             } else {
  273.                 if (!shouldPaint(x,y))
  274.                     in_border = TRUE;
  275.             }
  276.         }
  277.         return sp;
  278.     }
  279.   // ラスタリージョンの削除を行う関数
  280.     void delete(int sx1,int sx2,int sy,STACK *oldsp, STACK *stack, STACK *sp)
  281.     {
  282.         STACK *p,*q;
  283.         for (p=stack; p<=oldsp; p++) {
  284.             if (p->y == sy && sx1 <= p->x && p->x <= sx2) {
  285.                 p->mark = FALSE;
  286.                 for (q = oldsp+1; q<=sp; q++) {
  287.                     if (q->y == p->py && p->px1 <= q->x && q->x <= p->px2)
  288.                         q->mark = FALSE;
  289.                 }
  290.             }
  291.         }
  292.     }
  293.     STACK stack[STACKSIZE];
  294.     STACK *sp;
  295.     STACK *oldsp;
  296.     int sx,sx1,sx2,sy;
  297.     int px1,px2,py;
  298.  
  299.     sp = stack;
  300.     sp->x = x;
  301.     sp->y = y;
  302.     sp->px1 = 0;
  303.     sp->px2 = 0;
  304.     sp->py = 0;
  305.     sp->mark = TRUE;
  306.     while (sp >= stack) {
  307.         if (sp->mark) {
  308.             sx = sp->x;
  309.             sy = sp->y;
  310.             px1 = sp->px1;
  311.             px2 = sp->px2;
  312.             py = sp->py;
  313.             sx1 = srchleft(sx,sy);
  314.             //     for (sx1=sx,ip=(short*)EIMadrs(sx1,sy);
  315.             //         sx1 > 0 && *(ip-1) == border;
  316.             //         sx1--,ip--)
  317.             //        ;
  318.             sx2 = srchright(sx,sy);
  319.             //    for (sx2=sx,ip=(short*)EIMadrs(sx2,sy);
  320.             //         sx2 < EIMgetxsize()-1 && *(ip+1) == border;
  321.             //         sx2++,ip++)
  322.             //        ;
  323.             hline(sx1,sx2,sy);
  324.             oldsp = --sp;
  325.             sp=check(px1,px2,py,sx1,sx2,sy,sy+1, stack,STACKSIZE, sp);
  326.             sp=check(px1,px2,py,sx1,sx2,sy,sy-1, stack,STACKSIZE, sp);
  327.             delete(sx1,sx2,sy,oldsp, stack,sp);
  328.         } else
  329.             sp--;
  330.     }
  331. }
  332.  
  333. void do_blot(int x, int y, int branch, int depth,
  334.              void pset(int x,int y,int gray)!)
  335. // branch : 枝分かれする数
  336. // depth : 何回再帰するか
  337. // gray : 0..50 程度
  338. {
  339.     if (depth <= 0)
  340.         return;
  341.     deci branchsub = IntToDeci(branch)/_max(1,depth/3);
  342.     void blot_plot_sub(int x,int y,deci branch,int depth,
  343.                        deci grad, deci gradsub)
  344.     {
  345.         if (depth <= 0 || grad <= 0)
  346.             return;
  347.         pset(x,y,DeciToInt(grad));
  348.         int b;
  349.         for (b=0; b<_max(1,DeciToInt(branch)); b++)
  350.         {
  351.             int nx,ny;
  352.             nx = x + rand() % 3 - 1;
  353.             ny = y + rand() % 3 - 1;
  354.             blot_plot_sub(nx,ny,branch-branchsub,depth-1,grad-gradsub,gradsub);
  355.         }
  356.     }
  357.     blot_plot_sub(x,y,IntToDeci(branch),depth,
  358.                   IntToDeci(50),IntToDeci(50)/depth);
  359. }
  360.  
  361. #define MAXY 2000
  362.  
  363. static short **xbuf = NULL;    // ポリゴン指定用ワーク
  364. #define XBUFMAX 10
  365. #define    RIGHTMAX    0x7fff
  366.  
  367. void do_polygon(POINT* points, int nPoint, void hline(int x1,int x2,int y)!)
  368. {
  369.     if (xbuf == NULL)
  370.     {
  371.         if ((xbuf = TL_calloc(1,sizeof(short*)*MAXY)) == NULL)
  372.             return;
  373.         short* buf = TL_calloc(sizeof(short),XBUFMAX*MAXY);
  374.         if (buf == NULL)
  375.             { TL_free(xbuf); xbuf = NULL; return; }
  376.         for (int i=0; i<MAXY; i++)
  377.             xbuf[i] = buf + XBUFMAX*i;
  378.     }
  379.     int i;
  380.     for (i=0; i<MAXY; i++)
  381.         xbuf[i][0] = RIGHTMAX;
  382.     int getsign(int n)
  383.       { return (n<0 ? -1 : n>0 ? 1 : 0); }
  384.     int pnum = nPoint;    // 頂点の数
  385.     int f1,f2;
  386.     // 始点での頂点の例外処理のために、前の辺の符号をきめる
  387.     f1=0;
  388.     for (i=1; i<pnum; i++) {
  389.         f2=getsign(points[i].y-points[i-1].y);
  390.         if (f2!=0)
  391.             f1=f2;
  392.     }
  393.     f2=getsign(points[0].y-points[pnum-1].y);
  394.     if (f2!=0)
  395.         f1=f2;
  396.     // x 座標リストの作成
  397.     void makebuf(int x1,int y1,int x2,int y2)
  398.     {
  399.         void sort_x() // (x1,y1) をバッファに登録する
  400.         {
  401.             if (y1 < 0 || MAXY <= y1)
  402.                 return;
  403.             for (int i=0; i<XBUFMAX; i++)
  404.             {
  405.                 if (xbuf[y1][i] > x1)
  406.                 {
  407.                     if (i==XBUFMAX-1)
  408.                     {
  409.                         xbuf[y1][i] = x1;
  410.                         return;
  411.                     }
  412.                     for (int j=XBUFMAX-1; j>i; j--)
  413.                         xbuf[y1][j] = xbuf[y1][j-1];
  414.                     xbuf[y1][i] = x1;
  415.                     break;
  416.                 }
  417.             }
  418.         }
  419.         int f2;
  420.         f2 = getsign(y2-y1);
  421.         if (f2==0)
  422.             return;
  423.         if (f1*f2==-1)
  424.             sort_x();
  425.         int dx,dy,ux,uy;
  426.         dx = abs(x2-x1);
  427.         dy = abs(y2-y1);
  428.         ux = getsign(x2-x1);
  429.         uy = getsign(y2-y1);
  430.         if (dx >= dy) {
  431.             int r = dx/2;
  432.             for (;;) {
  433.                 if (x1==x2) {
  434.                     f1=f2;
  435.                     break;
  436.                 }
  437.                 x1 += ux, r += dy;
  438.                 if (r >= dx) {
  439.                     r -= dx, y1 += uy;
  440.                     sort_x();
  441.                 }
  442.             }
  443.         } else {
  444.             int r = dy/2;
  445.             for (;;) {
  446.                 if (y1==y2) {
  447.                     f1=f2;
  448.                     break;
  449.                 }
  450.                 y1 += uy, r += dx;
  451.                 if (r >= dy)
  452.                     r -= dy, x1 += ux;
  453.                 sort_x();
  454.             }
  455.         }
  456.     }
  457.     for (i=0; i<pnum-1; i++)
  458.         makebuf(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
  459.     makebuf(points[pnum-1].x,points[pnum-1].y,points[0].x,points[0].y);
  460.     for (i=0; i<MAXY; i++) {
  461.         for (int j=0; j<XBUFMAX; j+=2) {
  462.             if (_max(xbuf[i][j],xbuf[i][j+1]) < RIGHTMAX)
  463.                 hline(xbuf[i][j],xbuf[i][j+1],i);
  464.             else
  465.                 break;
  466.         }
  467.     }
  468. }
  469.  
  470.