home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix Heaven Sunny 2
/
APPARE2.BIN
/
oh_towns
/
art2
/
src.lzh
/
SUBGRP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-06-18
|
11KB
|
470 lines
/*
描画アルゴリズム
void do_line_cont(int x1,int y1,int x2,int y2,void func(int x,int y)!)
void do_line(int x1,int y1,int x2,int y2,void func(int x,int y)!)
do_paint
void do_blot(int x, int y, int branch, int depth,
void pset(int x,int y,int gray)!)
void do_polygon(POINT* points, int nPoint, void hline(int x1,int x2,int y)!)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winb.h>
#include <te.h>
#include <fntb.h>
#include <gui.h>
#include <egb.h>
#include <wgb.h>
#include <msdos.cf>
#include "art.h"
#include "guisub.h"
#include "wgbmac.H"
#include "subgrp.h"
#include "imath.h"
#define swap(a,b) { int t; t=(a); (a)=(b); (b)=t; }
/*--------------------------------------------------------*/
/* 描画アルゴリズム */
/*--------------------------------------------------------*/
void do_line_cont(int x1,int y1,int x2,int y2,void func(int x,int y)!)
{
int xr,yr,r,x,y;
xr=abs(x2-x1),yr=abs(y2-y1);
if (xr==0 && yr==0)
;
else if (xr > yr)
{
r=(yr<<16)/xr; if(y1>y2) r=-r;
if (x1 < x2)
for (x=x1+1,y=(y1<<16)+0x8000+r; x<=x2; x++,y+=r)
func(x,(y>>16));
else
for (x=x1-1,y=(y1<<16)+0x8000+r; x>=x2; x--,y+=r)
func(x,(y>>16));
}
else
{
r=(xr<<16)/yr; if(x1>x2) r=-r;
if (y1 < y2)
for (y=y1+1,x=(x1<<16)+0x8000+r; y<=y2; y++,x+=r)
func((x>>16),y);
else
for (y=y1-1,x=(x1<<16)+0x8000+r; y>=y2; y--,x+=r)
func((x>>16),y);
}
}
void do_line(int x1,int y1,int x2,int y2,void func(int x,int y)!)
{
func(x1,y1); // 最初の点
do_line_cont(x1,y1,x2,y2,func);
}
void do_boxline(int x1,int y1,int x2,int y2,void func(int x,int y)!)
{
int i;
if (x2<x1) swap(x1,x2);
if (y2<y1) swap(y1,y2);
for(i=x1;i<=x2;i++) func(i,y1);
if(y1<y2)
for(i=x1;i<=x2;i++) func(i,y2);
for(i=y1+1;i<y2;i++) func(x1,i);
if(x1<x2)
for(i=y1+1;i<y2;i++) func(x2,i);
}
void do_boxfill(int x1,int y1,int x2,int y2,void func(int x1,int x2,int y)!)
{
int i;
if (x2<x1) swap(x1,x2);
if (y2<y1) swap(y1,y2);
for(i=y1;i<=y2;i++) func(x1,x2,i);
}
void do_ellipse(int x,int y,int rx,int ry,void func(int x,int y)!)
{
#if 0
#define ELLIPSE(RX,RY,X0,Y0,X1,Y1) \
{ \
int x0=RX,s=x0; \
int y0=0; \
int px0=-1,py0=-1,px1=-1,py1=-1; \
while(x0>=y0) \
{ \
int x1=x0*RY/RX; \
int y1=y0*RY/RX; \
if(px0!=X0||py1!=Y1) \
{ \
func(x+X0,y+Y1);if(X0!=0)func(x-X0,y+Y1); \
if (Y1!=0) \
{ func(x+X0,y-Y1);if(X0!=0)func(x-X0,y-Y1); } \
} \
if (py0!=Y0||px1!=X1) \
{ \
func(x+Y0,y+X1);if(Y0!=0)func(x-Y0,y+X1); \
if (X1!=0) \
{ func(x+Y0,y-X1);if(Y0!=0)func(x-Y0,y-X1); } \
} \
s-=2*y0+1; if(s<0)s+=2*(x0-1),x0--; \
y0++; \
px0=X0,py0=Y0,px1=X1,py1=Y1; \
} \
}
#
if (rx==0 && ry==0)
func(x,y);
else if (rx>ry)
ELLIPSE(rx,ry,x0,y0,x1,y1)
else
ELLIPSE(ry,rx,x1,y1,x0,y0)
#undef ELLIPSE
#endif
if (rx==0 && ry==0)
{ func(x,y); return; }
int px,py,prey;
int a2,b2;
int c1,c2;
int e;
a2=rx*rx,b2=ry*ry;
px=0,py=ry;
c1=4*b2,c2=8*a2;
e=a2*(1-4*ry);
while(b2*px<=a2*py)
{
func(x+px,y+py); if(px!=0)func(x-px,y+py);
func(x+px,y-py); if(px!=0)func(x-px,y-py);
prey=py;
e+=c1*(2*px+1),px++; if(e>0) e-=c2*py,py--;
}
px=rx,py=0;
c1=4*a2,c2=8*b2;
e=b2*(1-4*rx);
while(a2*py<=b2*px && py<prey)
{
func(x+px,y+py); if(px!=0)func(x-px,y+py);
if(py!=0) { func(x+px,y-py); if(px!=0)func(x-px,y-py); }
e+=c1*(2*py+1),py++; if(e>0) e-=c2*px,px--;
}
}
void do_ellipsefill(int x,int y,int rx,int ry,void func(int x1,int x2,int y)!)
{
#if 0
#define ELLIPSE(RX,RY,X0,Y0,X1,Y1) \
{ \
int x0=RX,s=x0; \
int y0=0; \
int py0,py1; \
py0=py1=INT_MIN; \
while(x0>=y0) \
{ \
int x1=x0*RY/RX; \
int y1=y0*RY/RX; \
if (y+Y1 != py0) \
{ \
py0=y+Y1; \
func(x-X0,x+X0,py0); \
func(x-X0,x+X0,y-Y1); \
} \
if (y+X1 != py1) \
{ \
py1=y+X1; \
func(x-Y0,x+Y0,py1); \
func(x-Y0,x+Y0,y-X1); \
} \
s-=2*y0-1; if(s<0)s+=2*(x0-1),x0--; \
y0++; \
} \
}
#
if (rx==0&&ry==0)
func(x,x,y);
else if (rx>ry)
ELLIPSE(rx,ry,x0,y0,x1,y1)
else
ELLIPSE(ry,rx,x1,y1,x0,y0)
#undef ELLIPSE
#endif
if (rx==0 && ry==0)
{ func(x,x,y); return; }
int px,py,prey;
int a2,b2;
int c1,c2;
int e;
a2=rx*rx,b2=ry*ry;
px=0,py=ry;
c1=4*b2,c2=8*a2;
e=a2*(1-4*ry);
prey=-1;
while(b2*px<=a2*py)
{
e+=c1*(2*px+1);
if(e>0)
{
func(x-px,x+px,y+py); func(x-px,x+px,y-py);
prey=py;
e-=c2*py,py--;
}
px++;
}
px=rx,py=0;
c1=4*a2,c2=8*b2;
e=b2*(1-4*rx);
while(a2*py<=b2*px && py<prey)
{
func(x-px,x+px,y+py);
if(py!=0) func(x-px,x+px,y-py);
e+=c1*(2*py+1),py++; if(e>0) e-=c2*px,px--;
}
}
/*--------------------------------------------------------*/
/* ペイントルーチン */
/*--------------------------------------------------------*/
typedef struct {
short int x,y;
short int px1,px2,py;
BOOL mark;
} STACK;
void do_paint(int x,int y, int picwid, int picht,
void hline(int x1,int x2,int y)!,
BOOL shouldPaint(int x,int y)!, // point(x,y) == border
int srchleft(int x,int y)!,
int srchright(int x,int y)!)
{
#define STACKSIZE 600
// ラスタリージョンの追加を行う関数
STACK *check(int px1,int px2,int py,int sx1,int sx2,int sy,
int y, STACK *stack,int stacksize, STACK *sp)
// 新しい sp を返す
{
int x;
BOOL in_border;
if (y<0 || picht<=y)
return sp;
in_border = TRUE;
for (x=sx1; x<=sx2; x++) {
if (in_border) {
if (shouldPaint(x,y)) {
if (!(y==py&&px1<=x&&x<=px2) && sp+1 < stack+stacksize) {
sp++;
sp->x = x;
sp->y = y;
sp->px1 = sx1;
sp->px2 = sx2;
sp->py = sy;
sp->mark = TRUE;
}
in_border = FALSE;
}
} else {
if (!shouldPaint(x,y))
in_border = TRUE;
}
}
return sp;
}
// ラスタリージョンの削除を行う関数
void delete(int sx1,int sx2,int sy,STACK *oldsp, STACK *stack, STACK *sp)
{
STACK *p,*q;
for (p=stack; p<=oldsp; p++) {
if (p->y == sy && sx1 <= p->x && p->x <= sx2) {
p->mark = FALSE;
for (q = oldsp+1; q<=sp; q++) {
if (q->y == p->py && p->px1 <= q->x && q->x <= p->px2)
q->mark = FALSE;
}
}
}
}
STACK stack[STACKSIZE];
STACK *sp;
STACK *oldsp;
int sx,sx1,sx2,sy;
int px1,px2,py;
sp = stack;
sp->x = x;
sp->y = y;
sp->px1 = 0;
sp->px2 = 0;
sp->py = 0;
sp->mark = TRUE;
while (sp >= stack) {
if (sp->mark) {
sx = sp->x;
sy = sp->y;
px1 = sp->px1;
px2 = sp->px2;
py = sp->py;
sx1 = srchleft(sx,sy);
// for (sx1=sx,ip=(short*)EIMadrs(sx1,sy);
// sx1 > 0 && *(ip-1) == border;
// sx1--,ip--)
// ;
sx2 = srchright(sx,sy);
// for (sx2=sx,ip=(short*)EIMadrs(sx2,sy);
// sx2 < EIMgetxsize()-1 && *(ip+1) == border;
// sx2++,ip++)
// ;
hline(sx1,sx2,sy);
oldsp = --sp;
sp=check(px1,px2,py,sx1,sx2,sy,sy+1, stack,STACKSIZE, sp);
sp=check(px1,px2,py,sx1,sx2,sy,sy-1, stack,STACKSIZE, sp);
delete(sx1,sx2,sy,oldsp, stack,sp);
} else
sp--;
}
}
void do_blot(int x, int y, int branch, int depth,
void pset(int x,int y,int gray)!)
// branch : 枝分かれする数
// depth : 何回再帰するか
// gray : 0..50 程度
{
if (depth <= 0)
return;
deci branchsub = IntToDeci(branch)/_max(1,depth/3);
void blot_plot_sub(int x,int y,deci branch,int depth,
deci grad, deci gradsub)
{
if (depth <= 0 || grad <= 0)
return;
pset(x,y,DeciToInt(grad));
int b;
for (b=0; b<_max(1,DeciToInt(branch)); b++)
{
int nx,ny;
nx = x + rand() % 3 - 1;
ny = y + rand() % 3 - 1;
blot_plot_sub(nx,ny,branch-branchsub,depth-1,grad-gradsub,gradsub);
}
}
blot_plot_sub(x,y,IntToDeci(branch),depth,
IntToDeci(50),IntToDeci(50)/depth);
}
#define MAXY 2000
static short **xbuf = NULL; // ポリゴン指定用ワーク
#define XBUFMAX 10
#define RIGHTMAX 0x7fff
void do_polygon(POINT* points, int nPoint, void hline(int x1,int x2,int y)!)
{
if (xbuf == NULL)
{
if ((xbuf = TL_calloc(1,sizeof(short*)*MAXY)) == NULL)
return;
short* buf = TL_calloc(sizeof(short),XBUFMAX*MAXY);
if (buf == NULL)
{ TL_free(xbuf); xbuf = NULL; return; }
for (int i=0; i<MAXY; i++)
xbuf[i] = buf + XBUFMAX*i;
}
int i;
for (i=0; i<MAXY; i++)
xbuf[i][0] = RIGHTMAX;
int getsign(int n)
{ return (n<0 ? -1 : n>0 ? 1 : 0); }
int pnum = nPoint; // 頂点の数
int f1,f2;
// 始点での頂点の例外処理のために、前の辺の符号をきめる
f1=0;
for (i=1; i<pnum; i++) {
f2=getsign(points[i].y-points[i-1].y);
if (f2!=0)
f1=f2;
}
f2=getsign(points[0].y-points[pnum-1].y);
if (f2!=0)
f1=f2;
// x 座標リストの作成
void makebuf(int x1,int y1,int x2,int y2)
{
void sort_x() // (x1,y1) をバッファに登録する
{
if (y1 < 0 || MAXY <= y1)
return;
for (int i=0; i<XBUFMAX; i++)
{
if (xbuf[y1][i] > x1)
{
if (i==XBUFMAX-1)
{
xbuf[y1][i] = x1;
return;
}
for (int j=XBUFMAX-1; j>i; j--)
xbuf[y1][j] = xbuf[y1][j-1];
xbuf[y1][i] = x1;
break;
}
}
}
int f2;
f2 = getsign(y2-y1);
if (f2==0)
return;
if (f1*f2==-1)
sort_x();
int dx,dy,ux,uy;
dx = abs(x2-x1);
dy = abs(y2-y1);
ux = getsign(x2-x1);
uy = getsign(y2-y1);
if (dx >= dy) {
int r = dx/2;
for (;;) {
if (x1==x2) {
f1=f2;
break;
}
x1 += ux, r += dy;
if (r >= dx) {
r -= dx, y1 += uy;
sort_x();
}
}
} else {
int r = dy/2;
for (;;) {
if (y1==y2) {
f1=f2;
break;
}
y1 += uy, r += dx;
if (r >= dy)
r -= dy, x1 += ux;
sort_x();
}
}
}
for (i=0; i<pnum-1; i++)
makebuf(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
makebuf(points[pnum-1].x,points[pnum-1].y,points[0].x,points[0].y);
for (i=0; i<MAXY; i++) {
for (int j=0; j<XBUFMAX; j+=2) {
if (_max(xbuf[i][j],xbuf[i][j+1]) < RIGHTMAX)
hline(xbuf[i][j],xbuf[i][j+1],i);
else
break;
}
}
}