#help_index "Graphics/Math" I8 GrXOffsets[8]={-1,0,1,-1,1,-1,0,1}, GrYOffsets[8]={-1,-1,-1,0,0,1,1,1}; public void Line(void *aux_data, I8 x1,I8 y1,I8 z1, I8 x2,I8 y2,I8 z2, void plot_cb(void *aux,I8 x,I8 y,I8 z), I8 step=1,I8 start=0) { I8 i,j,d,dx=x2-x1,dy=y2-y1,dz=z2-z1; I8 adx=AbsI8(dx),ady=AbsI8(dy),adz=AbsI8(dz); if (adx>=ady) { if (adx>=adz) { if (d=adx) { if (dx>=0) dx=0x100000000; else dx=-0x100000000; dy=dy<<32/d; dz=dz<<32/d; } } else { if (d=adz) { dx=dx<<32/d; dy=dy<<32/d; if (dz>=0) dz=0x100000000; else dz=-0x100000000; } } } else { if (ady>=adz) { if (d=ady) { dx=dx<<32/d; if (dy>=0) dy=0x100000000; else dy=-0x100000000; dz=dz<<32/d; } } else { if (d=adz) { dx=dx<<32/d; dy=dy<<32/d; if (dz>=0) dz=0x100000000; else dz=-0x100000000; } } } x1<<=32; y1<<=32; z1<<=32; for (j=0;j=ady1) d1=(adx1>=adz1) ? adx1:adz1; else d1=(ady1>=adz1) ? ady1:adz1; d1<<=1; if (d1) { dx1=dx1<<32/d1; dy1=dy1<<32/d1; dz1=dz1<<32/d1; } if (adx2>=ady2) d2=(adx2>=adz2) ? adx2:adz2; else d2=(ady2>=adz2) ? ady2:adz2; d2<<=1; if (d2) { dx2=dx2<<32/d2; dy2=dy2<<32/d2; dz2=dz2<<32/d2; } x1<<=32; y1<<=32; z1<<=32; for (j=0;j<=d1;j++) { x2=x1; y2=y1; z2=z1; for (i=0;i<=d2;i++) { plot_cb(aux_data,x2.i4[1],y2.i4[1],z2.i4[1]); x2+=dx2; y2+=dy2; z2+=dz2; } x1+=dx1; y1+=dy1; z1+=dz1; } } #help_index "Graphics/Math/3D Transformation" I8 gr_scale; gr_scale.u4[0]=0; gr_scale.u4[1]=1; void *gr_screen_capture=NULL; public void GrRotate(I8 *r,I8 *x,I8 *y,I8 *z) { I8 x1,y1,z1,xx=*x,yy=*y,zz=*z; x1=(r[0]*xx+r[1]*yy+r[2]*zz+r[3])>>32; y1=(r[4]*xx+r[5]*yy+r[6]*zz+r[7])>>32; z1=(r[8]*xx+r[9]*yy+r[10]*zz+r[11])>>32; *x=x1;*y=y1;*z=z1; } public void GrTransform(GrBitMap *base,I8 *x,I8 *y,I8 *z) { GrRotate(base->r,x,y,z); *x+=base->x; *y+=base->y; *z+=base->z; } public I8 *GrTheta(double theta,TssStruct *tss=NULL) { double my_cos,my_sin; I8 *r=MAllocZ(sizeof(I8)*16,tss); my_cos=Cos(theta)*gr_scale; my_sin=Sin(theta)*gr_scale; r[0]=my_cos; r[5]=my_cos; r[4]=my_sin; r[1]=-my_sin; r[10]=gr_scale; return r; } public I8 *GrPhi(double phi,TssStruct *tss=NULL) { double my_cos,my_sin; I8 *r=MAllocZ(sizeof(I8)*16,tss); my_cos=Cos(phi)*gr_scale; my_sin=Sin(phi)*gr_scale; r[5]=my_cos; r[10]=my_cos; r[9]=my_sin; r[6]=-my_sin; r[0]=gr_scale; return r; } public I8 *GrScaleMat(I8 *m1,double s,TssStruct *tss=NULL) { I8 i,*r=MAllocZ(sizeof(I8)*16,tss); for (i=0;i<16;i++) r[i]=m1[i]*s; return r; } public I8 *GrMulMat(I8 *m1,I8 *m2,TssStruct *tss=NULL) { I8 *r=MAllocZ(sizeof(I8)*16,tss); I8 i,j,k; double d; for (i=0;i<4;i++) { for (j=0;j<4;j++) { for (k=0;k<4;k++) { d=m1[k+4*j]; d*=m2[i+4*k]; d/=gr_scale; r[i+4*j]+=d; } } } return r; } public I8 GrDetMat(I8 *m1) { I8 i; double m[16],d; for (i=0;i<16;i++) m[i]=m1[i]/(1.0*0x100000000); d=m[0]*(m[5]*m[10]-m[6]*m[9])- m[1]*(m[4]*m[10]-m[6]*m[8])+ m[2]*(m[4]*m[9]-m[5]*m[8]); return d*0x100000000; } public void GrScalePenWidth(GrBitMap *base) { I8 d; if (base->flags&BMF_TRANSFORMATION) { if (base->pen_width) { d=base->pen_width*GrDetMat(base->r)+0x80000000; base->pen_width=d.u4[1]; if (base->pen_width<1) base->pen_width=1; } } } public void GrSetIdent(I8 *r) { MemSet(r,0,16<<3); r[0].u4[1]=1; r[5].u4[1]=1; r[10].u4[1]=1; r[15].u4[1]=1; } public void GrSetTranslation(I8 *r,I8 x,I8 y,I8 z) { r[3]=x<<32; r[7]=y<<32; r[11]=z<<32; } #help_index "Graphics/Math" public void Circle(void *aux_data, I8 cx,I8 cy,I8 cz, I8 radius, void plot_cb(void *aux,I8 x,I8 y,I8 z), I8 step=1, double start_rad=0, double len_rad=pi2) { I8 i,j,len=len_rad*radius; I8 x,y,x1,y1,s1,s2,c; double t; if (radius<0) return; if (!radius) { plot_cb(aux_data,cx,cy,cz); return; } t=1.0/radius; s1=(1<<24)*Sin(t); s2=-s1; c=(1<<24)*Cos(t); if (start_rad) { x=radius*Cos(start_rad); y=-radius*Sin(start_rad); } else { x=radius; y=0; } x<<=8; y<<=8; for (i=0;i<=len;i+=step) { plot_cb(aux_data,cx+x>>8,cy+y>>8,cz); for (j=0;j>24; y1=(s2*x+c*y)>>24; x=x1; y=y1; } } } public void Ellipse(void *aux_data, I8 cx,I8 cy,I8 cz, I8 x_radius,I8 y_radius, void plot_cb(void *aux,I8 x,I8 y,I8 z), double rot_angle=0, I8 step=1, double start_rad=0, double len_rad=pi2) { I8 i,j,len; I8 x,y,x1,y1,x2,y2, s1,s2,c, s12,s22,c2; double t; if (x_radius<0 || y_radius<0 || step<1) return; if (!x_radius && !y_radius) { plot_cb(aux_data,cx,cy,cz); return; } if (x_radius>=y_radius) { t=1.0/x_radius; len=len_rad*x_radius; } else { t=1.0/y_radius; len=len_rad*y_radius; } s1=(1<<24)*Sin(t); s2=-s1; c=(1<<24)*Cos(t); s12=(1<<24)*Sin(rot_angle); s22=-s12; c2=(1<<24)*Cos(rot_angle); if (start_rad) { x=x_radius*Cos(start_rad); y=-x_radius*Sin(start_rad); } else { x=x_radius; y=0; } x<<=8; y<<=8; x2=x; y2=y; y1=y2*y_radius/x_radius; x=(c2*x2+s12*y1)>>24; y=(s22*x2+c2*y1)>>24; for (i=0;i<=len;i+=step) { plot_cb(aux_data,cx+x>>8,cy+y>>8,cz); for (j=0;j>24; y1=(s2*x2+c*y2)>>24; x2=x1; y2=y1; y1=y1*y_radius/x_radius; x=(c2*x1+s12*y1)>>24; y=(s22*x1+c2*y1)>>24; } } } public I8 DistP3I4(P3I4 *p1,P3I4 *p2) { return Sqrt(SqrI8(p1->x-p2->x)+SqrI8(p1->y-p2->y)+SqrI8(p1->z-p2->z)); } public void Bezier2(void *aux_data,P3I4 *ctrl,void plot_cb(void *aux,I8 x,I8 y,I8 z)) {//2nd order I8 x,y,z,xx,yy,zz,dx,dy,dz,d_max; double x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z; double x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0; double x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0; double t,d=DistP3I4(&ctrl[0],&ctrl[1])+ DistP3I4(&ctrl[1],&ctrl[2])+ DistP3I4(&ctrl[2],&ctrl[0]), s=0.5/d,t1,t2; xx=x0; yy=y0; zz=z0; for (t=0.0;t<=1.0;t+=s) { t1=t*(1.0-t); t2=t*t; x=x0+x1*t1+x2*t2; y=y0+y1*t1+y2*t2; z=z0+z1*t1+z2*t2; dx=AbsI8(x-xx); dy=AbsI8(y-yy); dz=AbsI8(z-zz); if (dx>dy) d_max=dx; else d_max=dy; if (dz>d_max) d_max=dz; if (!d_max) s*=1.1; else { s*=0.9; plot_cb(aux_data,x,y,z); xx=x;yy=y;zz=z; } } } public void Bezier3(void *aux_data,P3I4 *ctrl,void plot_cb(void *aux,I8 x,I8 y,I8 z)) { //3rd order I8 x,y,z,xx,yy,zz,dx,dy,dz,d_max; double x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z; double x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0; double x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0; double x3=ctrl[3].x-x0,y3=ctrl[3].y-y0,z3=ctrl[3].z-z0; double t,d=DistP3I4(&ctrl[0],&ctrl[1])+ DistP3I4(&ctrl[1],&ctrl[2])+ DistP3I4(&ctrl[2],&ctrl[3])+ DistP3I4(&ctrl[3],&ctrl[0]), s=0.5/d,nt,t1,t2,t3; xx=x0; yy=y0; zz=z0; for (t=0.0;t<=1.0;t+=s) { nt=1.0-t; t1=t*nt*nt; t2=t*t*nt; t3=t*t*t; x=x0+x1*t1+x2*t2+x3*t3; y=y0+y1*t1+y2*t2+y3*t3; z=z0+z1*t1+z2*t2+z3*t3; dx=AbsI8(x-xx); dy=AbsI8(y-yy); dz=AbsI8(z-zz); if (dx>dy) d_max=dx; else d_max=dy; if (dz>d_max) d_max=dz; if (!d_max) s*=1.1; else { s*=0.9; plot_cb(aux_data,x,y,z); xx=x;yy=y;zz=z; } } } public void BSpline2(void *aux_data,P3I4 *ctrl,I8 cnt,void plot_cb(void *aux,I8 x,I8 y,I8 z),BoolU4 closed=FALSE) { //2nd order I8 i,j; P3I4 *c; if (cnt<3) return; if (closed) { cnt++; c=MAlloc(sizeof(P3I4)*(cnt*2-1)); j=1; for (i=0;i