#help_index "Graphics/Math" public I64 gr_x_offsets[8]={-1, 0, 1,-1,1,-1,0,1}, gr_y_offsets[8]={-1,-1,-1, 0,0, 1,1,1}, gr_x_offsets2[4]={ 0,-1, 1, 0}, gr_y_offsets2[4]={-1, 0, 0, 1}; public Bool Line(U8 *aux_data,I64 x1,I64 y1,I64 z1,I64 x2,I64 y2,I64 z2, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),I64 step=1,I64 start=0) {//Step through line segment calling callback. //Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.HC"$. I64 i,j,d,dx=x2-x1,dy=y2-y1,dz=z2-z1,_x,_y,_z, adx=AbsI64(dx),ady=AbsI64(dy),adz=AbsI64(dz); Bool first=TRUE; 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;jflags&DCF_TRANSFORMATION) { if (dc->thick) { d=dc->thick*dc->r_norm+0x80000000; //Round dc->thick=d.i32[1]; if (dc->thick<1) dc->thick=1; } } } public I64 *Mat4x4TranslationEqu(I64 *r,I64 x,I64 y,I64 z) {//Set translation values in 4x4 matrix. Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.HC"$. r[0*4+3]=x<<32; r[1*4+3]=y<<32; r[2*4+3]=z<<32; r[3*4+3]=GR_SCALE; return r; } public I64 *Mat4x4TranslationAdd(I64 *r,I64 x,I64 y,I64 z) {//Add translation to 4x4 matrix. Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.HC"$. r[0*4+3]+=x<<32; r[1*4+3]+=y<<32; r[2*4+3]+=z<<32; r[3*4+3]=GR_SCALE; return r; } public Bool DCSymmetrySet(CDC *dc=gr.dc,I64 x1,I64 y1,I64 x2,I64 y2) {//2D. Set device context's symmetry. F64 d; if (y1==y2 && x1==x2) return FALSE; dc->sym.snx=y2-y1; dc->sym.sny=x1-x2; dc->sym.snz=0; if (d=Sqrt(SqrI64(dc->sym.snx)+ SqrI64(dc->sym.sny)+ SqrI64(dc->sym.snz))) { d=GR_SCALE/d; dc->sym.snx *= d; dc->sym.sny *= d; dc->sym.snz *= d; } dc->sym.sx=x1; dc->sym.sy=y1; dc->sym.sz=0; return TRUE; } public Bool DCSymmetry3Set(CDC *dc=gr.dc,I64 x1,I64 y1,I64 z1, I64 x2,I64 y2,I64 z2,I64 x3,I64 y3,I64 z3) {//3D. Set device context's symmetry. F64 d,x,y,z,xx,yy,zz; I64 xx1,yy1,zz1,xx2,yy2,zz2,*r; xx1=x1-x2; yy1=y1-y2; zz1=z1-z2; xx2=x3-x2; yy2=y3-y2; zz2=z3-z2; if (!xx1 && !yy1 && !zz1 || !xx2 && !yy2 && !zz2 || xx1==xx2 && yy1==yy2 && zz1==zz2) return FALSE; x=yy1*zz2-zz1*yy2; y=-xx1*zz2+zz1*xx2; z=xx1*yy2-yy1*xx2; if (dc->flags & DCF_TRANSFORMATION) { r=dc->r; xx=x*r[0]+y*r[1]+z*r[2]; yy=x*r[4]+y*r[5]+z*r[6]; zz=x*r[8]+y*r[9]+z*r[10]; x=xx; y=yy; z=zz; } if (d=Sqrt(Sqr(x)+Sqr(y)+Sqr(z))) { d=GR_SCALE/d; dc->sym.snx = d*x; dc->sym.sny = d*y; dc->sym.snz = d*z; } if (dc->flags & DCF_TRANSFORMATION) (*dc->transform)(dc,&x1,&y1,&z1); dc->sym.sx=x1; dc->sym.sy=y1; dc->sym.sz=z1; return TRUE; } public U0 DCReflect(CDC *dc,I64 *_x,I64 *_y,I64 *_z) {//Reflect 3D point about device context's symmetry. Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.HC"$. I64 x=*_x<<32,y=*_y<<32,z=*_z<<32, xx=*_x-dc->sym.sx,yy=*_y-dc->sym.sy,zz=*_z-dc->sym.sz, d=(xx*dc->sym.snx+yy*dc->sym.sny+zz*dc->sym.snz)>>16, xn,yn,zn,xx2,yy2,zz2; xn=d*dc->sym.snx>>15; yn=d*dc->sym.sny>>15; zn=d*dc->sym.snz>>15; xx=x-xn; yy=y-yn; zz=z-zn; xx2=x+xn; yy2=y+yn; zz2=z+zn; if (SqrI64(xx>>16 -dc->sym.sx<<16)+ SqrI64(yy>>16 -dc->sym.sy<<16)+ SqrI64(zz>>16 -dc->sym.sz<<16)< SqrI64(xx2>>16-dc->sym.sx<<16)+ SqrI64(yy2>>16-dc->sym.sy<<16)+ SqrI64(zz2>>16-dc->sym.sz<<16)) { *_x=xx.i32[1]; *_y=yy.i32[1]; *_z=zz.i32[1]; } else { *_x=xx2.i32[1]; *_y=yy2.i32[1]; *_z=zz2.i32[1]; } } #help_index "Graphics/Math" #define GR_SCALE1_BITS 24 #define GR_SCALE2_BITS 8 public Bool Circle(U8 *aux_data,I64 cx,I64 cy,I64 cz,I64 radius, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z), I64 step=1,F64 start_radians=0,F64 len_radians=2*ã) {//Step through circle arc calling callback. I64 i,j,len=Ceil(len_radians*radius), x,y,x1,y1,s1,s2,c; F64 t; if (radius<=0||!step) return TRUE; t=1.0/radius; c=1<>GR_SCALE2_BITS,cy+y>>GR_SCALE2_BITS,cz)) return FALSE; for (j=0;j>GR_SCALE1_BITS; y1=(s2*x+c*y)>>GR_SCALE1_BITS; x=x1; y=y1; } } return TRUE; } public Bool Ellipse(U8 *aux_data,I64 cx,I64 cy,I64 cz, I64 x_radius,I64 y_radius,Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z), F64 rot_angle=0,I64 step=1,F64 start_radians=0,F64 len_radians=2*ã) {//Step through ellipse arc calling callback. I64 i,j,len, x,y,_x,_y,x1,y1,x2,y2, s1,s2,c, s12,s22,c2; F64 t; Bool first=TRUE; if (x_radius<=0 || y_radius<=0 || !step) return TRUE; if (x_radius>=y_radius) { t=1.0/x_radius; len=Ceil(len_radians*x_radius); } else { t=1.0/y_radius; len=Ceil(len_radians*y_radius); } c=1<>GR_SCALE1_BITS; y=(s22*x2+c2*y1)>>GR_SCALE1_BITS; for (i=0;i<=len;i+=step) { if ((x>>GR_SCALE2_BITS!=_x || y>>GR_SCALE2_BITS!=_y || first) && !(*fp_plot)(aux_data,cx+x>>GR_SCALE2_BITS,cy+y>>GR_SCALE2_BITS,cz)) return FALSE; _x=x>>GR_SCALE2_BITS; _y=y>>GR_SCALE2_BITS; first=FALSE; for (j=0;j>GR_SCALE1_BITS; y1=(s2*x2+c*y2)>>GR_SCALE1_BITS; x2=x1; y2=y1; y1=y1*y_radius/x_radius; x=(c2*x1+s12*y1)>>GR_SCALE1_BITS; y=(s22*x1+c2*y1)>>GR_SCALE1_BITS; } } return TRUE; } public Bool RegPoly(U8 *aux_data,I64 cx,I64 cy,I64 cz, I64 x_radius,I64 y_radius,I64 sides, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z), F64 rot_angle=0,I64 step=1,F64 start_radians=0,F64 len_radians=2*ã) {//Step through regular polygon calling callback. I64 i,n,x,y,x1,y1,x2,y2, xx1,yy1,xx2,yy2, s1,s2,c, s12,s22,c2; F64 angle_step; if (sides<=0 || x_radius<=0 || y_radius<=0) return TRUE; angle_step=2*ã/sides; n=len_radians*sides/(2*ã); s1=1<>GR_SCALE1_BITS; y=(s22*x2+c2*y1)>>GR_SCALE1_BITS; xx1=cx+x>>GR_SCALE2_BITS; yy1=cy+y>>GR_SCALE2_BITS; for (i=0;i>GR_SCALE1_BITS; y1=(s2*x2+c*y2)>>GR_SCALE1_BITS; x2=x1; y2=y1; y1=y1*y_radius/x_radius; x=(c2*x1+s12*y1)>>GR_SCALE1_BITS; y=(s22*x1+c2*y1)>>GR_SCALE1_BITS; xx2=cx+x>>GR_SCALE2_BITS; yy2=cy+y>>GR_SCALE2_BITS; if (!Line(aux_data,xx1,yy1,cz,xx2,yy2,cz,fp_plot,step)) return FALSE; xx1=xx2; yy1=yy2; } return TRUE; } #help_index "Graphics/Data Types/D3I32;Math/Data Types/D3I32;Data Types/D3I32" public F64 D3I32Dist(CD3I32 *p1,CD3I32 *p2) {//Distance return Sqrt(SqrI64(p1->x-p2->x)+SqrI64(p1->y-p2->y)+SqrI64(p1->z-p2->z)); } public I64 D3I32DistSqr(CD3I32 *p1,CD3I32 *p2) {//Distance Squared return SqrI64(p1->x-p2->x)+SqrI64(p1->y-p2->y)+SqrI64(p1->z-p2->z); } public F64 D3I32Norm(CD3I32 *p) {//Norm return Sqrt(SqrI64(p->x)+SqrI64(p->y)+SqrI64(p->z)); } public I64 D3I32NormSqr(CD3I32 *p) {//Norm Squared return SqrI64(p->x)+SqrI64(p->y)+SqrI64(p->z); } #help_index "Graphics/Math" public Bool Bezier2(U8 *aux_data,CD3I32 *ctrl, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool first=TRUE) {//Go in 2nd order bezier calling callback. I64 x,y,z,xx,yy,zz,dx,dy,dz,d_max; F64 x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z, x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0, x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0, t,d=D3I32Dist(&ctrl[0],&ctrl[1])+ D3I32Dist(&ctrl[1],&ctrl[2])+ D3I32Dist(&ctrl[2],&ctrl[0]), s=0.5/d,t1,t2; xx=x0; yy=y0; zz=z0; if (first && !(*fp_plot)(aux_data,xx,yy,zz)) return FALSE; 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=AbsI64(x-xx); dy=AbsI64(y-yy); dz=AbsI64(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; if (!(*fp_plot)(aux_data,x,y,z)) return FALSE; xx=x;yy=y;zz=z; } } x=ctrl[2].x; y=ctrl[2].y; z=ctrl[2].z; if ((xx!=x || yy!=y || zz!=z) && !(*fp_plot)(aux_data,x,y,z)) return FALSE; return TRUE; } public Bool Bezier3(U8 *aux_data,CD3I32 *ctrl, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool first=TRUE) {//Go in 3rd order bezier calling callback. I64 x,y,z,xx,yy,zz,dx,dy,dz,d_max; F64 x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z, x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0, x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0, x3=ctrl[3].x-x0,y3=ctrl[3].y-y0,z3=ctrl[3].z-z0, t,d=D3I32Dist(&ctrl[0],&ctrl[1])+ D3I32Dist(&ctrl[1],&ctrl[2])+ D3I32Dist(&ctrl[2],&ctrl[3])+ D3I32Dist(&ctrl[3],&ctrl[0]), s=0.5/d,nt,t1,t2,t3; xx=x0; yy=y0; zz=z0; if (first && !(*fp_plot)(aux_data,xx,yy,zz)) return FALSE; 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=AbsI64(x-xx); dy=AbsI64(y-yy); dz=AbsI64(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; if (!(*fp_plot)(aux_data,x,y,z)) return FALSE; xx=x;yy=y;zz=z; } } x=ctrl[3].x; y=ctrl[3].y; z=ctrl[3].z; if ((xx!=x || yy!=y || zz!=z) && !(*fp_plot)(aux_data,x,y,z)) return FALSE; return TRUE; } public Bool BSpline2(U8 *aux_data,CD3I32 *ctrl,I64 cnt, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool closed=FALSE) {//Go in 2nd order spline calling callback. I64 i,j; CD3I32 *c; Bool first; if (cnt<3) return FALSE; first=TRUE; if (closed) { cnt++; c=MAlloc(sizeof(CD3I32)*(cnt*2-1)); j=1; for (i=0;ibottom) cc1=CC_BOTTOM; else if (y1right) cc1|=CC_RIGHT; else if (x1bottom) cc2=CC_BOTTOM; else if (y2right) cc2|=CC_RIGHT; else if (x2bottom) cc1=CC_BOTTOM; else if (y1right) cc1|=CC_RIGHT; else if (x1bottom) cc2=CC_BOTTOM; else if (y2right) cc2|=CC_RIGHT; else if (x2