#pragma On(Align_all_labels)
#pragma On(Align_labels)

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#include <concorde.h>
#include <tomahawk.h>

#include <airforce.h>


#define makeTri3D(d,s,a,b,c) d[ 0]=3;\
                           d[ 1]=s[(a)*3];d[ 2]=s[(a)*3+1];d[ 3]=s[(a)*3+2];\
                           d[ 4]=s[(b)*3];d[ 5]=s[(b)*3+1];d[ 6]=s[(b)*3+2];\
                           d[ 7]=s[(c)*3];d[ 8]=s[(c)*3+1];d[ 9]=s[(c)*3+2];

#define makeQuad3D(d,s,l,m,n,o) d[ 0]=4;\
                           d[ 1]=s[(l)*3];d[ 2]=s[(l)*3+1];d[ 3]=s[(l)*3+2];\
                           d[ 4]=s[(m)*3];d[ 5]=s[(m)*3+1];d[ 6]=s[(m)*3+2];\
                           d[ 7]=s[(n)*3];d[ 8]=s[(n)*3+1];d[ 9]=s[(n)*3+2];\
                           d[10]=s[(o)*3];d[11]=s[(o)*3+1];d[12]=s[(o)*3+2];

#define polygon3D(dp,pl2,pl1,cpz,atr) if(ClipPolyg3D(pl2,pl1,cpz)){\
            Projection(pl2[0],pl2+1,pl2+1,atr); \
            if(YGH_triangleArea(dp,AL_area,AL_ed,pl2)==0)\
            	         YGH_areaPaint(dp,AL_area,AL_ed);}



#define makeTri2D(d,s,a,b,c) d[ 0]=3;\
                           d[ 1]=s[(a)*2];d[ 2]=s[(a)*2+1];\
                           d[ 3]=s[(b)*2];d[ 4]=s[(b)*2+1];\
                           d[ 5]=s[(c)*2];d[ 6]=s[(c)*2+1];

#define makeQuad2D(d,s,l,m,n,o) d[ 0]=4;\
                           d[ 1]=s[(l)*2];d[ 2]=s[(l)*2+1];\
                           d[ 3]=s[(m)*2];d[ 4]=s[(m)*2+1];\
                           d[ 5]=s[(n)*2];d[ 6]=s[(n)*2+1];\
                           d[ 7]=s[(o)*2];d[ 8]=s[(o)*2+1];



typedef struct objindex {
	int code;
	union {
		int posi[6];
		struct {
			int sx,sy,col;
		} grid;
		struct {
			int unit;
			int ox,oy,oz;
			int wdir;
			int wdr[2];
		} lax;
		struct {
			int x1,y1,x2,y2,col;
		} line;
		struct {
			int x,y,r,col;
		} circ;
		struct {
			char *bm;
			int bmx,bmy,x1,y1,x2,y2;
		} bmap;
	} posi;
	int *dat;
	int z;
	int flying;
	struct objindex *prev;
	struct objindex *next;
} STRBUF;

	


int AL_Sizeof_Str(int *str);
void AL_Write_Mountain(PAGE *dp,STRBUF *st,int *sit);
void AL_Write_Building(PAGE *dp,STRBUF *st,int *sit);
void AL_Write_Polygon(PAGE *dp,STRBUF *s,int *sit);
void AL_Write_Bridge(PAGE *dp,STRBUF *s,int *sit);
void AL_Write_Mountain_Flying(PAGE *dp,STRBUF *s,int *sit);
void AL_Write_Building_Flying(PAGE *dp,STRBUF *s,int *sit);
void AL_Write_Polygon_Flying(PAGE *dp,STRBUF *s,int *sit);



int *AL_area=NULL,AL_ed[4];
int AL_objmax;
STRBUF *AL_stbuf=NULL;
PRJSCRN AL_prj;

static int nobj;
static STRBUF *top;
static int eye[6];


int AL_Get_Init_Size(int *arsiz,int *bfsiz,int ylin,int omax)
{
	*arsiz = sizeof(int) * 16 * ylin;
	*bfsiz = sizeof(STRBUF) * omax;
	return 0;
}

int AL_Init_All_Ref(int omax,char *ar,char *bf)
{
	AL_area=(int *)ar;
	AL_stbuf=(STRBUF *)bf;
	AL_objmax=omax;

	return 0;
}

int AL_Init_All(int ylin,int omax)
{
	int *ar;
	STRBUF *bf;

	if((ar=(int *)malloc( sizeof(int) * 16 * ylin))==NULL)return -1;
	if((bf=(STRBUF *)malloc( sizeof(STRBUF) * omax))==NULL)return -1;

	AL_area=ar;
	AL_stbuf=bf;
	AL_objmax=omax;

	return  0;
}


int AL_Set_Eye(int *pos,PRJSCRN *prj)
{
	int i;

	AL_stbuf[0].code=STR_EOF;
	AL_stbuf[0].z=INT_MIN;
	AL_stbuf[0].prev=NULL;
	AL_stbuf[0].next=NULL;

	top=&AL_stbuf[0];
	nobj=1;

	for(i=0; i<6; i++)eye[i]=pos[i];

	AL_prj=(*prj);

	return 0;
}


void AL_Insert_Lax(LAXIS *lax)
{
	int dv,*str,pnt[3],wdr[2],sit[6],ox,oy,oz;
	STRBUF *app,*prv;

	sit[0]=FxSinHq(eye[3]);
	sit[1]=FxCosHq(eye[3]);
	sit[2]=FxSinHq(eye[4]);
	sit[3]=FxCosHq(eye[4]);
	sit[4]=FxSinHq(eye[5]);
	sit[5]=FxCosHq(eye[5]);

	wdr[0]=FxSinHq((*lax).wdir);
	wdr[1]=FxCosHq((*lax).wdir);

	switch((*lax).unit)
	{
	case UNI_METER:
		dv=1;
		ox=(*lax).wcx-eye[0]/100;
		oy=          -eye[1]/100;
		oz=(*lax).wcz-eye[2]/100;
		break;
	case UNI_CENTI:
		dv=100;
		ox=(*lax).wcx-eye[0];
		oy=          -eye[1];
		oz=(*lax).wcz-eye[2];
		break;
	}

	if(_abs(ox)>MAX_SIGHT ||
	   _abs(oy)>MAX_SIGHT ||
	   _abs(oz)>MAX_SIGHT)return;
	
	for(str=(*lax).str;
		*str!=STR_EOF && nobj<AL_objmax;
		str+=AL_Sizeof_Str(str))
	{
		if(*str==STR_RUNWAY || *str==STR_HAZARD)continue;

		pnt[0]=str[5];
		pnt[2]=str[7];
		RotFast(pnt,pnt+2,wdr);
		pnt[0]=(pnt[0]+(*lax).wcx)/dv-eye[0]/100;
		pnt[1]= str[6]            /dv-eye[1]/100;
		pnt[2]=(pnt[2]+(*lax).wcz)/dv-eye[2]/100;
		RotGtoVFast(1,pnt,pnt,sit);

		if(pnt[2]+str[11]/dv < AL_prj.cpz/100 ||  /* 後ろにあるとき */
		   _abs(pnt[0])>=MAX_SIGHT ||             /* 遠すぎるとき */
		   _abs(pnt[1])>=MAX_SIGHT ||
		   _abs(pnt[2])>=MAX_SIGHT)continue;

		for(app=top; (*app).z>pnt[2]; app=(*app).next);

		prv=(*app).prev;
		if(prv)(*prv).next = &AL_stbuf[nobj];
		  else         top = &AL_stbuf[nobj];
		(*app).prev        = &AL_stbuf[nobj];

		AL_stbuf[nobj].code            = str[0];
		AL_stbuf[nobj].posi.lax.unit   = (*lax).unit;
		AL_stbuf[nobj].posi.lax.ox     = ox;
		AL_stbuf[nobj].posi.lax.oy     = oy;
		AL_stbuf[nobj].posi.lax.oz     = oz;
		AL_stbuf[nobj].posi.lax.wdir   = (*lax).wdir;
		AL_stbuf[nobj].posi.lax.wdr[0] = wdr[0];
		AL_stbuf[nobj].posi.lax.wdr[1] = wdr[1];
		AL_stbuf[nobj].dat             = str;
		AL_stbuf[nobj].z               = pnt[2];
		AL_stbuf[nobj].flying          = (pnt[2]-str[11]/dv > AL_prj.cpz/100);
		AL_stbuf[nobj].prev            = prv;
		AL_stbuf[nobj].next            = app;
		nobj++;
	}

	return;
}

int AL_Sizeof_Str(int *str)  /* Used in function AL_Insert_Lax */
{
	int siztbl[]=
	{
		1,
		HEAD_STR+6,
		HEAD_STR+8,
		0,
		HEAD_STR+5,
		HEAD_STR,
		HEAD_STR
	};

	if(*str!=STR_POLYGON)return siztbl[*str];
	else                 return HEAD_STR+5+str[HEAD_STR+4]*2;
}





void AL_Insert_Bitmap(char *bm,int bmx,int bmy,int xsiz,int ysiz,int *pos)
{
	int bmp[3];
	STRBUF *prv;
	register int z;
	register STRBUF *app;

	if(nobj>=AL_objmax)return;

	bmp[0]=pos[0]-eye[0];
	bmp[1]=pos[1]-eye[1];
	bmp[2]=pos[2]-eye[2];
	if(_abs(bmp[0])>MAX_SIGHT ||
	   _abs(bmp[1])>MAX_SIGHT ||
	   _abs(bmp[2])>MAX_SIGHT)return;

	RotGtoVHq(1,bmp,bmp,eye+3);
	if(bmp[2]<=AL_prj.cpz)return;
	z=bmp[2]/100;
	xsiz = xsiz *AL_prj.prj.mag /bmp[2]/2;
	ysiz = ysiz *AL_prj.prj.mag /bmp[2]/2;
	Projection(1,bmp,bmp,&AL_prj.prj);
	for(app=top; (app->z)>z; app=(app->next));

	prv=app->prev;
	if(prv)prv->next = &AL_stbuf[nobj];
	  else       top = &AL_stbuf[nobj];
	app->prev = &AL_stbuf[nobj];

	AL_stbuf[nobj].code=STR_BITMAP;
	AL_stbuf[nobj].posi.bmap.bm=bm;
	AL_stbuf[nobj].posi.bmap.x1=bmp[0]-xsiz;
	AL_stbuf[nobj].posi.bmap.y1=bmp[1]-xsiz;
	AL_stbuf[nobj].posi.bmap.x2=bmp[0]+xsiz-1;
	AL_stbuf[nobj].posi.bmap.y2=bmp[1]+xsiz-1;
	AL_stbuf[nobj].posi.bmap.bmx=bmx;
	AL_stbuf[nobj].posi.bmap.bmy=bmy;
	AL_stbuf[nobj].z=z;
	AL_stbuf[nobj].flying=0;
	AL_stbuf[nobj].prev=prv;
	AL_stbuf[nobj].next=app;
	nobj++;
}



void AL_Insert_Model(int *sld,int *pos)
{
	int sldp[3],r;
	STRBUF *prv;
	register int z;
	register STRBUF *app;

	if(nobj>=AL_objmax)return;

	sldp[0]=pos[0]-eye[0];
	sldp[1]=pos[1]-eye[1];
	sldp[2]=pos[2]-eye[2];
	if(_abs(sldp[0])>MAX_SIGHT ||
	   _abs(sldp[1])>MAX_SIGHT ||
	   _abs(sldp[2])>MAX_SIGHT)return;

	RotGtoVHq(1,sldp,sldp,eye+3);

	r=sld[6];
	if(sld[4]==0)r*=100;
	if(sldp[2]+r<=AL_prj.cpz)return;

	z=sldp[2]/100;
	for(app=top; (*app).z>z; app=(*app).next);

	prv=(*app).prev;
	if(prv)(*prv).next = &AL_stbuf[nobj];
	  else         top = &AL_stbuf[nobj];
	(*app).prev        = &AL_stbuf[nobj];

	AL_stbuf[nobj].code=STR_SURF;
	AL_stbuf[nobj].posi.posi[0]=pos[0];
	AL_stbuf[nobj].posi.posi[1]=pos[1];
	AL_stbuf[nobj].posi.posi[2]=pos[2];
	AL_stbuf[nobj].posi.posi[3]=pos[3];
	AL_stbuf[nobj].posi.posi[4]=pos[4];
	AL_stbuf[nobj].posi.posi[5]=pos[5];
	AL_stbuf[nobj].dat=sld;
	AL_stbuf[nobj].z=z;
	AL_stbuf[nobj].flying=0;
	AL_stbuf[nobj].prev=prv;
	AL_stbuf[nobj].next=app;
	nobj++;
}


void AL_Insert_Grid(int col,int *pos)
{
	int grdp[3];
	STRBUF *prv;
	register int z;
	register STRBUF *app;

	if(nobj>=AL_objmax)return;

	grdp[0]=pos[0]-eye[0];
	grdp[1]=pos[1]-eye[1];
	grdp[2]=pos[2]-eye[2];
	if(_abs(grdp[0])>MAX_SIGHT ||
	   _abs(grdp[1])>MAX_SIGHT ||
	   _abs(grdp[2])>MAX_SIGHT)return;

	RotGtoVHq(1,grdp,grdp,eye+3);

	if(grdp[2]<=AL_prj.cpz)return;

	z=grdp[2]/100;
	Projection(1,grdp,grdp,&AL_prj.prj);
	for(app=top; (*app).z>z; app=(*app).next);

	prv=(*app).prev;
	if(prv)(*prv).next = &AL_stbuf[nobj];
	  else         top = &AL_stbuf[nobj];
	(*app).prev = &AL_stbuf[nobj];

	AL_stbuf[nobj].code=STR_GRID;
	AL_stbuf[nobj].posi.grid.sx=grdp[0];
	AL_stbuf[nobj].posi.grid.sy=grdp[1];
	AL_stbuf[nobj].posi.grid.col=col;
	AL_stbuf[nobj].z=z;
	AL_stbuf[nobj].flying=0;
	AL_stbuf[nobj].prev=prv;
	AL_stbuf[nobj].next=app;
	nobj++;
}

void AL_Insert_Line(int col,int *pos)
{
	int grdp[6];
	STRBUF *prv;
	register int z;
	register STRBUF *app;

	if(nobj>=AL_objmax)return;

	grdp[0]=pos[0]-eye[0];
	grdp[1]=pos[1]-eye[1];
	grdp[2]=pos[2]-eye[2];
	grdp[3]=pos[3]-eye[0];
	grdp[4]=pos[4]-eye[1];
	grdp[5]=pos[5]-eye[2];
	if(_abs(grdp[0])>MAX_SIGHT ||
	   _abs(grdp[1])>MAX_SIGHT ||
	   _abs(grdp[2])>MAX_SIGHT ||
	   _abs(grdp[3])>MAX_SIGHT ||
	   _abs(grdp[4])>MAX_SIGHT ||
	   _abs(grdp[5])>MAX_SIGHT)return;

	RotGtoVHq(2,grdp,grdp,eye+3);

	if(ClipLine3D(grdp,grdp,AL_prj.cpz)==1)return;

	z=(grdp[2]+grdp[5])/200;
	Projection(2,grdp,grdp,&AL_prj.prj);
	for(app=top; (*app).z>z; app=(*app).next);

	prv=(*app).prev;
	if(prv)(*prv).next = &AL_stbuf[nobj];
	  else         top = &AL_stbuf[nobj];
	(*app).prev = &AL_stbuf[nobj];

	AL_stbuf[nobj].code=STR_LINE;
	AL_stbuf[nobj].posi.line.x1=grdp[0];
	AL_stbuf[nobj].posi.line.y1=grdp[1];
	AL_stbuf[nobj].posi.line.x2=grdp[2];
	AL_stbuf[nobj].posi.line.y2=grdp[3];
	AL_stbuf[nobj].posi.line.col=col;
	AL_stbuf[nobj].z=z;
	AL_stbuf[nobj].flying=0;
	AL_stbuf[nobj].prev=prv;
	AL_stbuf[nobj].next=app;
	nobj++;
}

void AL_Insert_Circle(int col,int *pos,int r)
{
	int grdp[3];
	STRBUF *prv;
	register int z;
	register STRBUF *app;

	if(nobj>=AL_objmax)return;

	grdp[0]=pos[0]-eye[0];
	grdp[1]=pos[1]-eye[1];
	grdp[2]=pos[2]-eye[2];
	if(_abs(grdp[0])>MAX_SIGHT ||
	   _abs(grdp[1])>MAX_SIGHT ||
	   _abs(grdp[2])>MAX_SIGHT)return;

	RotGtoVHq(1,grdp,grdp,eye+3);
	if(grdp[2]<=AL_prj.cpz)return;
	z=grdp[2]/100;
	r=r* AL_prj.prj.mag/ grdp[2];
	Projection(1,grdp,grdp,&AL_prj.prj);
	for(app=top; (*app).z>z; app=(*app).next);

	prv=(*app).prev;
	if(prv)(*prv).next = &AL_stbuf[nobj];
	  else         top = &AL_stbuf[nobj];
	(*app).prev = &AL_stbuf[nobj];

	AL_stbuf[nobj].code=STR_CIRCLE;
	AL_stbuf[nobj].posi.circ.col=col;
	AL_stbuf[nobj].posi.circ.x=grdp[0];
	AL_stbuf[nobj].posi.circ.y=grdp[1];
	AL_stbuf[nobj].posi.circ.r=r;
	AL_stbuf[nobj].z=z;
	AL_stbuf[nobj].flying=0;
	AL_stbuf[nobj].prev=prv;
	AL_stbuf[nobj].next=app;
	nobj++;
}



int AL_Flush_Buffer(PAGE *p)
{
	int sit[6];
	STRBUF *ptr;

	sit[0]=FxSinHq(eye[3]);
	sit[1]=FxCosHq(eye[3]);
	sit[2]=FxSinHq(eye[4]);
	sit[3]=FxCosHq(eye[4]);
	sit[4]=FxSinHq(eye[5]);
	sit[5]=FxCosHq(eye[5]);

	for(ptr=top; (*ptr).code!=STR_EOF; ptr=(*ptr).next)
	{
		if((*ptr).flying==0)
		{
			switch((*ptr).code)
			{
			case STR_MOUNTAIN:
				AL_Write_Mountain(p,ptr,sit);
				break;
			case STR_BUILDING:
				AL_Write_Building(p,ptr,sit);
				break;
			case STR_POLYGON:
				AL_Write_Polygon(p,ptr,sit);
				break;
			case STR_BRIDGE:
				AL_Write_Bridge(p,ptr,sit);
				break;
			case STR_SURF:
				AL_Model(p,(*ptr).dat,(*ptr).posi.posi,eye,&AL_prj);
				break;
			case STR_LINE:
				YGH_color(p,(*ptr).posi.line.col);
				YGH_line(p,(*ptr).posi.line.x1,(*ptr).posi.line.y1,
				           (*ptr).posi.line.x2,(*ptr).posi.line.y2);
				break;
			case STR_GRID:
				YGH_color(p,(*ptr).posi.grid.col);
				YGH_pset(p,(*ptr).posi.grid.sx,(*ptr).posi.grid.sy);
				break;
			case STR_CIRCLE:
				YGH_color(p,(*ptr).posi.circ.col);
				if(AL_area==NULL)break;
				if(YGH_circleArea(p,AL_area,AL_ed,
				                  (*ptr).posi.circ.x,
				                  (*ptr).posi.circ.y,
				                  (*ptr).posi.circ.r)!=0)break;
				YGH_areaPaint(p,AL_area,AL_ed);
				break;
			case STR_BITMAP:
				YGH_putZoom(p,ptr->posi.bmap.bm,
				              ptr->posi.bmap.bmx,ptr->posi.bmap.bmy,
				              ptr->posi.bmap.x1, ptr->posi.bmap.y1,
				              ptr->posi.bmap.x2, ptr->posi.bmap.y2);
				break;
			}
		}
		else
		{
			switch((*ptr).code)
			{
			case STR_MOUNTAIN:
				AL_Write_Mountain_Flying(p,ptr,sit);
				break;
			case STR_BUILDING:
				AL_Write_Building_Flying(p,ptr,sit);
				break;
			case STR_POLYGON:
				AL_Write_Polygon_Flying(p,ptr,sit);
				break;
			case STR_BRIDGE:
				AL_Write_Bridge(p,ptr,sit);
				break;
			case STR_SURF:
				AL_Model(p,(*ptr).dat,(*ptr).posi.posi,eye,&AL_prj);
				break;
			}
		}
	}
	return 0;
}


void AL_Write_Mountain(PAGE *dp,STRBUF *s,int *sit)
{
	int p[30],pl1[16],pl2[32],*dat,ldr[2],*wdr;
	int lx,lz,cx,cy,cz,cpz;

/* 共通部分 */
	dat=(*s).dat;

	ldr[0]=FxSinHq(dat[8]+(*s).posi.lax.wdir);
	ldr[1]=FxCosHq(dat[8]+(*s).posi.lax.wdir);

	wdr=(*s).posi.lax.wdr;

	cx=dat[5];
	cz=dat[7];
	RotFast(&cx,&cz,wdr);
	cx+=(*s).posi.lax.ox;
	cy =(*s).posi.lax.oy;
	cz+=(*s).posi.lax.oz;

	switch((*s).posi.lax.unit)
	{
	case UNI_METER:
		cpz=AL_prj.cpz/100;
		break;
	case UNI_CENTI:
		cpz=AL_prj.cpz;
		break;
	}
/* 共通部分 */

	lx=dat[HEAD_STR+4];
	lz=dat[HEAD_STR+5];

	p[ 0]= lx;    p[ 1] =cy;    p[ 2]= lz;  RotFast(p+ 0,p+ 2,ldr);
	p[ 3]= lx;    p[ 4] =cy;    p[ 5]=-lz;  RotFast(p+ 3,p+ 5,ldr);
	p[ 6]=-lx;    p[ 7] =cy;    p[ 8]=-lz;  RotFast(p+ 6,p+ 8,ldr);
	p[ 9]=-lx;    p[10] =cy;    p[11]= lz;  RotFast(p+ 9,p+11,ldr);
	p[12]=-lx+lz; p[13] =cy+lz; p[14] =0;   RotFast(p+12,p+14,ldr);
	p[15]= lx-lz; p[16] =cy+lz; p[17] =0;   RotFast(p+15,p+17,ldr);

	p[ 0]+=cx; p[ 2]+=cz;
	p[ 3]+=cx; p[ 5]+=cz;
	p[ 6]+=cx; p[ 8]+=cz;
	p[ 9]+=cx; p[11]+=cz;
	p[12]+=cx; p[14]+=cz;
	p[15]+=cx; p[17]+=cz;

	p[18]= 256; p[19]= 256; p[20]= 0;
	RotFast(p+18,p+20,ldr);
	p[21]=-256; p[22]= 256; p[23]= 0;
	RotFast(p+21,p+23,ldr);
	p[24]=   0; p[25]= 256; p[26]= 256;
	RotFast(p+24,p+26,ldr);
	p[27]=   0; p[28]= 256; p[29]=-256;
	RotFast(p+27,p+29,ldr);

	RotGtoVFast(10,p,p,sit);

	if(InnerSgn(p+18,p+15)<0)
	{
		YGH_color(dp,dat[HEAD_STR+0]);
		makeTri3D(pl1,p,0,1,5);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+21,p+12)<0)
	{
		YGH_color(dp,dat[HEAD_STR+1]);
		makeTri3D(pl1,p,2,3,4);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+24,p+15)<0)
	{
		YGH_color(dp,dat[HEAD_STR+2]);
		makeQuad3D(pl1,p,0,3,4,5);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+27,p+15)<0)
	{
		YGH_color(dp,dat[HEAD_STR+3]);
		makeQuad3D(pl1,p,1,2,4,5);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
}



void AL_Write_Building(PAGE *dp,STRBUF *s,int *sit)
{
	int p[48],pl1[16],pl2[32],*dat,ldr[2],*wdr;
	int lx,lz,hi,cx,cy,cz,cpz;

/* 共通部分 */
	dat=(*s).dat;

	ldr[0]=FxSinHq(dat[8]+(*s).posi.lax.wdir);
	ldr[1]=FxCosHq(dat[8]+(*s).posi.lax.wdir);

	wdr=(*s).posi.lax.wdr;

	cx=dat[5];
	cz=dat[7];
	RotFast(&cx,&cz,wdr);
	cx+=(*s).posi.lax.ox;
	cy =(*s).posi.lax.oy;
	cz+=(*s).posi.lax.oz;

	switch((*s).posi.lax.unit)
	{
	case UNI_METER:
		cpz=AL_prj.cpz/100;
		break;
	case UNI_CENTI:
		cpz=AL_prj.cpz;
		break;
	}
/* 共通部分 */

	lx=dat[HEAD_STR+5];
	lz=dat[HEAD_STR+6];
	hi=dat[HEAD_STR+7];

	p[ 0]= lx; p[ 1] =cy   ; p[ 2]= lz;  RotFast(p+ 0,p+ 2,ldr);
	p[ 3]= lx; p[ 4] =cy   ; p[ 5]=-lz;  RotFast(p+ 3,p+ 5,ldr);
	p[ 6]=-lx; p[ 7] =cy   ; p[ 8]=-lz;  RotFast(p+ 6,p+ 8,ldr);
	p[ 9]=-lx; p[10] =cy   ; p[11]= lz;  RotFast(p+ 9,p+11,ldr);

	p[ 0]+=cx; p[ 2]+=cz;
	p[ 3]+=cx; p[ 5]+=cz;
	p[ 6]+=cx; p[ 8]+=cz;
	p[ 9]+=cx; p[11]+=cz;

	p[12]=p[ 0]; p[13] =cy+hi; p[14]=p[ 2];
	p[15]=p[ 3]; p[16] =cy+hi; p[17]=p[ 5];
	p[18]=p[ 6]; p[19] =cy+hi; p[20]=p[ 8];
	p[21]=p[ 9]; p[22] =cy+hi; p[23]=p[11];

	p[24]= 256; p[25]=   0; p[26]=   0;
	RotFast(p+24,p+26,ldr);
	p[27]=   0; p[28]=   0; p[29]=-256;
	RotFast(p+27,p+29,ldr);
	p[30]=-256; p[31]=   0; p[32]=   0;
	RotFast(p+30,p+32,ldr);
	p[33]=   0; p[34]=   0; p[35]= 256;
	RotFast(p+33,p+35,ldr);
	p[36]=   0; p[37]= 256; p[38]=   0;
	RotFast(p+36,p+38,ldr);

	RotGtoVFast(13,p,p,sit);

	if(InnerSgn(p+24,p+ 0)<0)
	{
		YGH_color(dp,dat[HEAD_STR+0]);
		makeQuad3D(pl1,p,0,1,5,4);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+27,p+ 3)<0)
	{
		YGH_color(dp,dat[HEAD_STR+1]);
		makeQuad3D(pl1,p,1,2,6,5);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+30,p+ 6)<0)
	{
		YGH_color(dp,dat[HEAD_STR+2]);
		makeQuad3D(pl1,p,2,3,7,6);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+33,p+ 9)<0)
	{
		YGH_color(dp,dat[HEAD_STR+3]);
		makeQuad3D(pl1,p,0,3,7,4);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	if(InnerSgn(p+36,p+12)<0)
	{
		YGH_color(dp,dat[HEAD_STR+4]);
		makeQuad3D(pl1,p,4,5,6,7);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
}


void AL_Write_Polygon(PAGE *dp,STRBUF *s,int *sit)
{
	int pl1[1+MAX_POINTS*6],pl2[1+MAX_POINTS*6],pl3[16],*dat,*wdr;
	int i,pts,x1,z1,x2,z2,hi,cx,cy,cz,cpz;

/* 共通部分 */
	dat=(*s).dat;

	wdr=(*s).posi.lax.wdr;

	cx=dat[5];
	cz=dat[7];
	RotFast(&cx,&cz,wdr);
	cx+=(*s).posi.lax.ox;
	cy =(*s).posi.lax.oy;
	cz+=(*s).posi.lax.oz;

	switch((*s).posi.lax.unit)
	{
	case UNI_METER:
		cpz=AL_prj.cpz/100;
		break;
	case UNI_CENTI:
		cpz=AL_prj.cpz;
		break;
	}
/* 共通部分 */

	dat+=HEAD_STR;

	hi=dat[3];
	pts=dat[4];
	pl1[0]=pts;
	i=pts-1;
	x2=dat[5+i*2];  z2=dat[6+i*2];
	pl3[ 7]=x2;  pl3[ 8]=0+cy;  pl3[ 9]=z2;  RotFast(pl3+7,pl3+9,wdr);
	pl3[ 7]+=cx; pl3[ 9]+=cz;
	pl3[10]=pl3[7]; pl3[11]=hi+cy; pl3[12]=pl3[9];
	RotGtoVFast(2,pl3+7,pl3+7,sit);
	for(i=0; i<pts; i++)
	{
		YGH_color(dp,dat[1+(i&1)]);
		pl3[ 0]=4;
		pl3[ 1]=pl3[10];  pl3[ 2]=pl3[11];  pl3[ 3]=pl3[12];
		pl3[ 4]=pl3[ 7];  pl3[ 5]=pl3[ 8];  pl3[ 6]=pl3[ 9];

		x1=x2;  z1=z2;
		x2=dat[5+i*2];  z2=dat[6+i*2];
		pl3[ 7]=x2;     pl3[ 8]= 0+cy;  pl3[ 9]=z2;
		pl3[13]=z1-z2;  pl3[14]= 0   ;  pl3[15]=x2-x1;
		RotFast(pl3+ 7,pl3+ 9,wdr);
		RotFast(pl3+13,pl3+15,wdr);
		pl3[ 7]+=cx;    pl3[ 9]+=cz;
		pl3[10]=pl3[7];  pl3[11]=hi+cy;  pl3[12]=pl3[9];
		RotGtoVFast(3,pl3+7,pl3+7,sit);
		pl1[1+i*3]=pl3[1]; pl1[2+i*3]=pl3[2]; pl1[3+i*3]=pl3[3];
		if(InnerSgn(pl3+1,pl3+13)<0)polygon3D(dp,pl2,pl3,cpz,&AL_prj.prj);
	}

	if(hi+cy<0 && ClipPolyg3D(pl2,pl1,cpz))
	{
		Projection(pl2[0],pl2+1,pl2+1,&AL_prj.prj);
		YGH_color(dp,dat[0]);
		if(YGH_polygonArea(dp,AL_area,AL_ed,pl2)==0)
					YGH_areaPaint(dp,AL_area,AL_ed);
	}
}


void AL_Write_Polygon_Flying
     (PAGE *dp,STRBUF *s,int *sit)
{
	int pl1[1+MAX_POINTS*2],pl2[1+MAX_POINTS*2],pl3[9],*dat,*wdr;
	int i,pts,x1,z1,x2,z2,hi,cx,cy,cz;

/* 共通部分 */
	dat=(*s).dat;

	wdr=(*s).posi.lax.wdr;

	cx=dat[5];
	cz=dat[7];
	RotFast(&cx,&cz,wdr);
	cx+=(*s).posi.lax.ox;
	cy =(*s).posi.lax.oy;
	cz+=(*s).posi.lax.oz;
/* 共通部分 */

	dat+=HEAD_STR;

	hi=dat[3];
	pts=dat[4];
	pl1[0]=pts;
	pl2[0]=4;
	i=pts-1;
	x2=dat[5+i*2];  z2=dat[6+i*2];
	pl3[ 0]=x2;  pl3[ 1]=0+cy;  pl3[ 2]=z2;  RotFast(pl3+0,pl3+2,wdr);
	pl3[ 0]+=cx; pl3[ 2]+=cz;
	pl3[ 3]=pl3[0]; pl3[ 4]=hi+cy; pl3[ 5]=pl3[2];
	RotGtoVFast(2,pl3,pl3,sit);
	Projection(2,pl2+5,pl3,&AL_prj.prj);

	for(i=0; i<pts; i++)
	{
		pl2[1]=pl2[7];
		pl2[2]=pl2[8];
		pl2[3]=pl2[5];
		pl2[4]=pl2[6];

		x1=x2;  z1=z2;
		x2=dat[5+i*2];  z2=dat[6+i*2];
		pl3[ 0]=x2   ;  pl3[ 1]= 0+cy;  pl3[ 2]=z2   ;
		pl3[ 6]=z1-z2;  pl3[ 7]= 0   ;  pl3[ 8]=x2-x1;
		RotFast(pl3   ,pl3+ 2,wdr);
		RotFast(pl3+ 6,pl3+ 8,wdr);
		pl3[ 0]+=cx;    pl3[ 2]+=cz;
		pl3[ 3]=pl3[0];  pl3[ 4]=hi+cy;  pl3[ 5]=pl3[2];
		RotGtoVFast(3,pl3,pl3,sit);
		Projection(2,pl2+5,pl3,&AL_prj.prj);

		pl1[1+i*2]=pl2[1]; pl1[2+i*2]=pl2[2];
		if(InnerSgn(pl3,pl3+6)<0)
			if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
			{
				YGH_color(dp,dat[1+(i&1)]);
				YGH_areaPaint(dp,AL_area,AL_ed);
			}
	}

	if(hi+cy<0)
	{
		if(!YGH_polygonArea(dp,AL_area,AL_ed,pl1))
		{
			YGH_color(dp,dat[0]);
			YGH_areaPaint(dp,AL_area,AL_ed);
		}
	}
}


void AL_Write_Bridge(PAGE *dp,STRBUF *s,int *sit)
{
	int p[32],pl1[16],pl2[32],*dat,ldr[2],*wdr;
	int lx,lz,hi,cx,cy,cz,cpz;

/* 共通部分 */
	dat=(*s).dat;

	ldr[0]=FxSinHq(dat[8]+(*s).posi.lax.wdir);
	ldr[1]=FxCosHq(dat[8]+(*s).posi.lax.wdir);

	wdr=(*s).posi.lax.wdr;

	cx=dat[5];
	cz=dat[7];
	RotFast(&cx,&cz,wdr);
	cx+=(*s).posi.lax.ox;
	cy =(*s).posi.lax.oy;
	cz+=(*s).posi.lax.oz;

	switch((*s).posi.lax.unit)
	{
	case UNI_METER:
		cpz=AL_prj.cpz/100;
		break;
	case UNI_CENTI:
		cpz=AL_prj.cpz;
		break;
	}
/* 共通部分 */

	dat+=HEAD_STR;
	lx=dat[2];
	lz=dat[3];
	hi=dat[4];

	p[ 0]= lx;   p[ 1]= cy;    p[ 2]= lz;  RotFast(p+0,  p+2,  ldr);
	p[ 3]= lx;   p[ 4]= cy;    p[ 5]=-lz;  RotFast(p+3,  p+5,  ldr);
	p[ 6]=-lx;   p[ 7]= cy;    p[ 8]=-lz;  RotFast(p+6,  p+8,  ldr);
	p[ 9]=-lx;   p[10]= cy;    p[11]= lz;  RotFast(p+9,  p+11, ldr);
	p[12]= lx-hi;p[13]= cy+hi; p[14]= lz;  RotFast(p+12, p+14, ldr);
	p[15]= lx-hi;p[16]= cy+hi; p[17]=-lz;  RotFast(p+15, p+17, ldr);
	p[18]=-lx+hi;p[19]= cy+hi; p[20]=-lz;  RotFast(p+18, p+20, ldr);
	p[21]=-lx+hi;p[22]= cy+hi; p[23]= lz;  RotFast(p+21, p+23, ldr);
	p[24]= 256;  p[25]=256;    p[26]=  0;  RotFast(p+24, p+26, ldr);

	p[ 0]+=cx; p[ 2]+=cz;
	p[ 3]+=cx; p[ 5]+=cz;
	p[ 6]+=cx; p[ 8]+=cz;
	p[ 9]+=cx; p[11]+=cz;
	p[12]+=cx; p[14]+=cz;
	p[15]+=cx; p[17]+=cz;
	p[18]+=cx; p[20]+=cz;
	p[21]+=cx; p[23]+=cz;

	RotGtoVFast(9,p,p,sit);

	YGH_color(dp,dat[1]);
	if(InnerSgn(p+24,p)<0)
	{
		makeQuad3D(pl1,p,2,3,7,6);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
		makeQuad3D(pl1,p,0,1,5,4);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}
	else
	{
		makeQuad3D(pl1,p,0,1,5,4);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
		makeQuad3D(pl1,p,2,3,7,6);
		polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
	}

	YGH_color(dp,dat[0]);
	makeQuad3D(pl1,p,4,5,6,7);
	polygon3D(dp,pl2,pl1,cpz,&AL_prj.prj);
}


//void AL_Write_Mountain_Flying(PAGE *dp,STRBUF *s,int *sit)
//{
//	int p[32],pl1[32],pl2[32],*dat,ldr[2],*wdr;
//	int lx,lz,cx,cy,cz;
//
///* 共通部分 */
//	dat=(*s).dat;
//
//	ldr[0]=FxSinHq(dat[8]+(*s).posi.lax.wdir);
//	ldr[1]=FxCosHq(dat[8]+(*s).posi.lax.wdir);
//
//	wdr=(*s).posi.lax.wdr;
//
//	cx=dat[5];
//	cz=dat[7];
//	RotFast(&cx,&cz,wdr);
//	cx+=(*s).posi.lax.ox;
//	cy =(*s).posi.lax.oy;
//	cz+=(*s).posi.lax.oz;
///* 共通部分 */
//
//	lx=dat[HEAD_STR+4];
//	lz=dat[HEAD_STR+5];
//
//	p[ 0]= lx;    p[ 1] =cy;    p[ 2]= lz;  RotFast(p+ 0,p+ 2,ldr);
//	p[ 3]= lx;    p[ 4] =cy;    p[ 5]=-lz;  RotFast(p+ 3,p+ 5,ldr);
//	p[ 6]=-lx;    p[ 7] =cy;    p[ 8]=-lz;  RotFast(p+ 6,p+ 8,ldr);
//	p[ 9]=-lx;    p[10] =cy;    p[11]= lz;  RotFast(p+ 9,p+11,ldr);
//	p[12]=-lx+lz; p[13] =cy+lz; p[14] =0;   RotFast(p+12,p+14,ldr);
//	p[15]= lx-lz; p[16] =cy+lz; p[17] =0;   RotFast(p+15,p+17,ldr);
//
//	p[ 0]+=cx; p[ 2]+=cz;
//	p[ 3]+=cx; p[ 5]+=cz;
//	p[ 6]+=cx; p[ 8]+=cz;
//	p[ 9]+=cx; p[11]+=cz;
//	p[12]+=cx; p[14]+=cz;
//	p[15]+=cx; p[17]+=cz;
//
//	p[18]= 256; p[19]= 256; p[20]= 0;
//	RotFast(p+18,p+20,ldr);
//	p[21]=-256; p[22]= 256; p[23]= 0;
//	RotFast(p+21,p+23,ldr);
//	p[24]=   0; p[25]= 256; p[26]= 256;
//	RotFast(p+24,p+26,ldr);
//	p[27]=   0; p[28]= 256; p[29]=-256;
//	RotFast(p+27,p+29,ldr);
//
//	RotGtoVFast(10,p,p,sit);
//	Projection(6,pl1,p,&AL_prj.prj);
//
//	if(InnerSgn(p+18,p+15)<0)
//	{
//		makeTri2D(pl2,pl1,0,1,5);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+0]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//	if(InnerSgn(p+21,p+12)<0)
//	{
//		makeTri2D(pl2,pl1,2,3,4);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+1]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//		
//	}
//	if(InnerSgn(p+24,p+15)<0)
//	{
//		makeQuad2D(pl2,pl1,0,3,4,5);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+2]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//	if(InnerSgn(p+27,p+15)<0)
//	{
//		makeQuad2D(pl2,pl1,1,2,4,5);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+3]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//}



//void AL_3D_WriteBuf_Building_Flying(PAGE *dp,STRBUF *s,int *sit)
//{
//	int p[48],pl1[48],pl2[32],*dat,ldr[2],*wdr;
//	int lx,lz,hi,cx,cy,cz;
//
///* 共通部分 */
//	dat=(*s).dat;
//
//	ldr[0]=FxSinHq(dat[8]+(*s).posi.lax.wdir);
//	ldr[1]=FxCosHq(dat[8]+(*s).posi.lax.wdir);
//
//	wdr=(*s).posi.lax.wdr;
//
//	cx=dat[5];
//	cz=dat[7];
//	RotFast(&cx,&cz,wdr);
//	cx+=(*s).posi.lax.ox;
//	cy =(*s).posi.lax.oy;
//	cz+=(*s).posi.lax.oz;
///* 共通部分 */
//
//	lx=dat[HEAD_STR+5];
//	lz=dat[HEAD_STR+6];
//	hi=dat[HEAD_STR+7];
//
//	p[ 0]= lx; p[ 1] =cy   ; p[ 2]= lz;  RotFast(p+ 0,p+ 2,ldr);
//	p[ 3]= lx; p[ 4] =cy   ; p[ 5]=-lz;  RotFast(p+ 3,p+ 5,ldr);
//	p[ 6]=-lx; p[ 7] =cy   ; p[ 8]=-lz;  RotFast(p+ 6,p+ 8,ldr);
//	p[ 9]=-lx; p[10] =cy   ; p[11]= lz;  RotFast(p+ 9,p+11,ldr);
//
//	p[ 0]+=cx; p[ 2]+=cz;
//	p[ 3]+=cx; p[ 5]+=cz;
//	p[ 6]+=cx; p[ 8]+=cz;
//	p[ 9]+=cx; p[11]+=cz;
//
//	p[12]=p[ 0]; p[13] =cy+hi; p[14]=p[ 2];
//	p[15]=p[ 3]; p[16] =cy+hi; p[17]=p[ 5];
//	p[18]=p[ 6]; p[19] =cy+hi; p[20]=p[ 8];
//	p[21]=p[ 9]; p[22] =cy+hi; p[23]=p[11];
//
//	p[24]= 256; p[25]=   0; p[26]=   0;
//	RotFast(p+24,p+26,ldr);
//	p[27]=   0; p[28]=   0; p[29]=-256;
//	RotFast(p+27,p+29,ldr);
//	p[30]=-256; p[31]=   0; p[32]=   0;
//	RotFast(p+30,p+32,ldr);
//	p[33]=   0; p[34]=   0; p[35]= 256;
//	RotFast(p+33,p+35,ldr);
//	p[36]=   0; p[37]= 256; p[38]=   0;
//	RotFast(p+36,p+38,ldr);
//
//	RotGtoVFast(13,p,p,sit);
//	Projection(8,pl1,p,&AL_prj.prj);
//
//	if(InnerSgn(p+24,p+ 0)<0)
//	{
//		makeQuad2D(pl2,pl1,0,1,5,4);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+0]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//	if(InnerSgn(p+27,p+ 3)<0)
//	{
//		makeQuad2D(pl2,pl1,1,2,6,5);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+1]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//	if(InnerSgn(p+30,p+ 6)<0)
//	{
//		makeQuad2D(pl2,pl1,2,3,7,6);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+2]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//	if(InnerSgn(p+33,p+ 9)<0)
//	{
//		makeQuad2D(pl2,pl1,0,3,7,4);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+3]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//	if(InnerSgn(p+36,p+12)<0)
//	{
//		makeQuad2D(pl2,pl1,4,5,6,7);
//		if(!YGH_triangleArea(dp,AL_area,AL_ed,pl2))
//		{
//			YGH_color(dp,dat[HEAD_STR+4]);
//			YGH_areaPaint(dp,AL_area,AL_ed);
//		}
//	}
//}
