#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 fixed-point. 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; j<start; j++) { x1+=dx; y1+=dy; z1+=dz; } if (step!=1 && step!=0) { dx*=step; dy*=step; dz*=step; d/=step; } for (i=start; i<=d; i++) { if ((_x!=x1.i32[1] || _y!=y1.i32[1] || _z!=z1.i32[1] || first) && !(*fp_plot)(aux_data,x1.i32[1],y1.i32[1],z1.i32[1])) return FALSE; first=FALSE; _x=x1.i32[1]; _y=y1.i32[1]; _z=z1.i32[1]; x1+=dx; y1+=dy; z1+=dz; } if (step==1 && (_x!=x2||_y!=y2||_z!=z2) && !(*fp_plot)(aux_data,x2,y2,z2)) return FALSE; return TRUE; } #help_index "Graphics/Math/3D Transformation" public U0 Mat4x4Print(I64 *m) {//Print a 4x4 matrix I64 i,j; "\n"; for (i=0; i<4; i++) { for (j=0; j<4; j++) { "%1.4f ",ToF64(m[i*4+j]); } "\n"; } } public I64 *Mat4x4MulMat4x4Equ(I64 *dst,I64 *m1,I64 *m2) {//Multiply 4x4 matrices and store in dst. Uses fixed-point. //Conceptually, the transform m1 is applied after m2 I64 i,j,k; F64 sum; for (i=0; i<4; i++) { for (j=0; j<4; j++) { sum=0; for (k=0; k<4; k++) sum+=ToF64(m1[k+4*j])*ToF64(m2[i+4*k]); dst[i+4*j]=sum/GR_SCALE; } } return dst; } public I64 *Mat4x4MulMat4x4New(I64 *m1,I64 *m2,CTask *mem_task=NULL) {//Multiply 4x4 matrices. Return MAlloced matrix. Uses fixed-point. //Conceptually, the transform m1 is applied after m2 return Mat4x4MulMat4x4Equ(MAlloc(sizeof(I64)*16,mem_task),m1,m2); } public I64 *Mat4x4Equ(I64 *dst,I64 *src) {//Copy 4x4 Rot matrix. MemCpy64(dst,src,16); return dst; } public I64 *Mat4x4New(I64 *src,CTask *mem_task=NULL) {//Return MAlloced copy of 4x4 Rot matrix. return Mat4x4Equ(MAlloc(sizeof(I64)*16,mem_task),src); } public I64 *Mat4x4RotX(I64 *m,F64 phi) {//Rot matrix about X axis. Uses fixed-point. F64 my_cos=Cos(phi)*GR_SCALE,my_sin=Sin(phi)*GR_SCALE; I64 r[4]; r[0]=(my_cos*ToF64(m[4])-my_sin*ToF64(m[8]))/GR_SCALE; r[1]=(my_cos*ToF64(m[5])-my_sin*ToF64(m[9]))/GR_SCALE; r[2]=(my_cos*ToF64(m[6])-my_sin*ToF64(m[10]))/GR_SCALE; r[3]=(my_cos*ToF64(m[7])-my_sin*ToF64(m[11]))/GR_SCALE; m[8]=(my_sin*ToF64(m[4])+my_cos*ToF64(m[8]))/GR_SCALE; m[9]=(my_sin*ToF64(m[5])+my_cos*ToF64(m[9]))/GR_SCALE; m[10]=(my_sin*ToF64(m[6])+my_cos*ToF64(m[10]))/GR_SCALE; m[11]=(my_sin*ToF64(m[7])+my_cos*ToF64(m[11]))/GR_SCALE; MemCpy64(&m[4],r,4); return m; } public I64 *Mat4x4RotXOld(I64 *m,F64 phi) {//Rot matrix about X axis. Uses fixed-point. F64 my_cos=Cos(phi)*GR_SCALE,my_sin=Sin(phi)*GR_SCALE; I64 r[16],r2[16]; MemSetI64(r,0,16); r[5]=my_cos; r[10]=my_cos; r[9]=my_sin; r[6]=-my_sin; r[0]=GR_SCALE; r[15]=GR_SCALE; return Mat4x4Equ(m,Mat4x4MulMat4x4Equ(r2,r,m)); } public I64 *Mat4x4RotY(I64 *m,F64 omega) {//Rot matrix about Y axis. Uses fixed-point. F64 my_cos=Cos(omega)*GR_SCALE,my_sin=Sin(omega)*GR_SCALE; I64 r[16],r2[16]; MemSetI64(&r[1],0,15); r[0]=my_cos; r[10]=my_cos; r[8]=-my_sin; r[2]=my_sin; r[5]=GR_SCALE; r[15]=GR_SCALE; return Mat4x4Equ(m,Mat4x4MulMat4x4Equ(r2,r,m)); } public I64 *Mat4x4RotZ(I64 *m,F64 theta) {//Rot matrix about Z axis. Uses fixed-point. F64 my_cos=Cos(theta)*GR_SCALE,my_sin=Sin(theta)*GR_SCALE; I64 r[4]; r[0]=(my_cos*ToF64(m[0])-my_sin*ToF64(m[4]))/GR_SCALE; r[1]=(my_cos*ToF64(m[1])-my_sin*ToF64(m[5]))/GR_SCALE; r[2]=(my_cos*ToF64(m[2])-my_sin*ToF64(m[6]))/GR_SCALE; r[3]=(my_cos*ToF64(m[3])-my_sin*ToF64(m[7]))/GR_SCALE; m[4]=(my_sin*ToF64(m[0])+my_cos*ToF64(m[4]))/GR_SCALE; m[5]=(my_sin*ToF64(m[1])+my_cos*ToF64(m[5]))/GR_SCALE; m[6]=(my_sin*ToF64(m[2])+my_cos*ToF64(m[6]))/GR_SCALE; m[7]=(my_sin*ToF64(m[3])+my_cos*ToF64(m[7]))/GR_SCALE; MemCpy64(m,r,4); return m; } public I64 *Mat4x4RotZOld(I64 *m,F64 theta) {//Rot matrix about Z axis. Uses fixed-point. F64 my_cos=Cos(theta)*GR_SCALE,my_sin=Sin(theta)*GR_SCALE; I64 r[16],r2[16]; MemSetI64(r,0,16); r[0]=my_cos; r[5]=my_cos; r[4]=my_sin; r[1]=-my_sin; r[10]=GR_SCALE; r[15]=GR_SCALE; return Mat4x4Equ(m,Mat4x4MulMat4x4Equ(r2,r,m)); } public I64 *Mat4x4Scale(I64 *m,F64 s) {//Scale 4x4 matrix by value. I64 i; for (i=0; i<16; i++) m[i]*=s; return m; } public U0 DCThickScale(CDC *dc=gr.dc) {//Scale device context's thick by norm of transformation. I64 d; if (dc->flags&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 fixed-point. 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 fixed-point. 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 DCReflectOld(CDC *dc,I64 *_x,I64 *_y,I64 *_z) {//Reflect 3D point about device context's symmetry. Uses fixed-point. 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]; } } public U0 DCReflect(CDC *dc,I64 *_x,I64 *_y,I64 *_z) {//Reflect 3D point about device context's symmetry. Uses fixed-point. 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,xx2,yy2,zz2; xx2=yy2=zz2=(xx*dc->sym.snx+yy*dc->sym.sny+zz*dc->sym.snz)>>16; xx2=xx2*dc->sym.snx>>15; yy2=yy2*dc->sym.sny>>15; zz2=zz2*dc->sym.snz>>15; xx=x-xx2; yy=y-yy2; zz=z-zz2; xx2=x+xx2; yy2=y+yy2; zz2=z+zz2; 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*pi) {//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_SCALE1_BITS*Cos(t); if (step<0) { step=-step; s2=1<<GR_SCALE1_BITS*Sin(t); s1=-s2; } else { s1=1<<GR_SCALE1_BITS*Sin(t); s2=-s1; } if (start_radians) { x=radius*Cos(start_radians); y=-radius*Sin(start_radians); } else { x=radius; y=0; } x<<=GR_SCALE2_BITS; y<<=GR_SCALE2_BITS; for (i=0; i<=len; i+=step) { if (!(*fp_plot)(aux_data,cx+x>>GR_SCALE2_BITS,cy+y>>GR_SCALE2_BITS,cz)) return FALSE; for (j=0; j<step; j++) { x1=(c*x+s1*y)>>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*pi) {//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*Cos(t); if (step<0) { step=-step; s2=1<<GR_SCALE1_BITS*Sin(t); s1=-s2; } else { s1=1<<GR_SCALE1_BITS*Sin(t); s2=-s1; } c2=1<<GR_SCALE1_BITS*Cos(rot_angle); s12=1<<GR_SCALE1_BITS*Sin(rot_angle); s22=-s12; if (start_radians) { x=x_radius*Cos(start_radians); y=-x_radius*Sin(start_radians); } else { x=x_radius; y=0; } x<<=GR_SCALE2_BITS; y<<=GR_SCALE2_BITS; x2=x; y2=y; y1=y2*y_radius/x_radius; x=(c2*x2+s12*y1)>>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<step; j++) { x1=(c*x2+s1*y2)>>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*pi) {//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*pi/sides; n=len_radians*sides/(2*pi); s1=1<<GR_SCALE1_BITS*Sin(angle_step); s2=-s1; c=1<<GR_SCALE1_BITS*Cos(angle_step); s12=1<<GR_SCALE1_BITS*Sin(rot_angle); s22=-s12; c2=1<<GR_SCALE1_BITS*Cos(rot_angle); if (start_radians) { x=x_radius*Cos(start_radians); y=-x_radius*Sin(start_radians); } else { x=x_radius; y=0; } x<<=GR_SCALE2_BITS; y<<=GR_SCALE2_BITS; x2=x; y2=y; y1=y2*y_radius/x_radius; x=(c2*x2+s12*y1)>>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<n; i++) { x1=(c*x2+s1*y2)>>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; i<cnt-2; i++) { c[j].x=(ctrl[i].x+ctrl[i+1].x)/2.0; c[j].y=(ctrl[i].y+ctrl[i+1].y)/2.0; c[j].z=(ctrl[i].z+ctrl[i+1].z)/2.0; j+=2; } c[j].x=(ctrl[0].x+ctrl[cnt-2].x)/2.0; c[j].y=(ctrl[0].y+ctrl[cnt-2].y)/2.0; c[j].z=(ctrl[0].z+ctrl[cnt-2].z)/2.0; c[0].x=(c[1].x+c[j].x)/2.0; c[0].y=(c[1].y+c[j].y)/2.0; c[0].z=(c[1].z+c[j].z)/2.0; j=2; for (i=0; i<cnt-2; i++) { c[j].x=(c[j-1].x+c[j+1].x)/2.0; c[j].y=(c[j-1].y+c[j+1].y)/2.0; c[j].z=(c[j-1].z+c[j+1].z)/2.0; j+=2; } c[j].x=c[0].x; c[j].y=c[0].y; c[j].z=c[0].z; } else { c=MAlloc(sizeof(CD3I32)*(cnt*2-1)); c[0].x=ctrl[0].x; c[0].y=ctrl[0].y; c[0].z=ctrl[0].z; c[cnt*2-2].x=ctrl[cnt-1].x; c[cnt*2-2].y=ctrl[cnt-1].y; c[cnt*2-2].z=ctrl[cnt-1].z; j=1; for (i=0; i<cnt-1; i++) { c[j].x=(ctrl[i].x+ctrl[i+1].x)/2.0; c[j].y=(ctrl[i].y+ctrl[i+1].y)/2.0; c[j].z=(ctrl[i].z+ctrl[i+1].z)/2.0; j+=2; } j=2; for (i=0; i<cnt-2; i++) { c[j].x=(c[j-1].x+c[j+1].x)/2.0; c[j].y=(c[j-1].y+c[j+1].y)/2.0; c[j].z=(c[j-1].z+c[j+1].z)/2.0; j+=2; } } for (i=0; i<cnt*2-2; i+=2) { if (!Bezier2(aux_data,&c[i],fp_plot,first)) return FALSE; first=FALSE; } Free(c); return TRUE; } public Bool BSpline3(U8 *aux_data,CD3I32 *ctrl,I64 cnt, Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool closed=FALSE) {//Go in 3rd order spline calling callback. I64 i,j; F64 x,y,z; CD3I32 *c; Bool first; if (cnt<3) return FALSE; first=TRUE; if (closed) { cnt++; c=MAlloc(sizeof(CD3I32)*(cnt*3-2)); j=1; for (i=0; i<cnt-2; i++) { x=ctrl[i].x; y=ctrl[i].y; z=ctrl[i].z; c[j].x=(ctrl[i+1].x-x)/3.0+x; c[j].y=(ctrl[i+1].y-y)/3.0+y; c[j].z=(ctrl[i+1].z-z)/3.0+z; j++; c[j].x=2.0*(ctrl[i+1].x-x)/3.0+x; c[j].y=2.0*(ctrl[i+1].y-y)/3.0+y; c[j].z=2.0*(ctrl[i+1].z-z)/3.0+z; j+=2; } x=ctrl[cnt-2].x; y=ctrl[cnt-2].y; z=ctrl[cnt-2].z; c[j].x=(ctrl[0].x-x)/3.0+x; c[j].y=(ctrl[0].y-y)/3.0+y; c[j].z=(ctrl[0].z-z)/3.0+z; j++; c[j].x=2.0*(ctrl[0].x-x)/3.0+x; c[j].y=2.0*(ctrl[0].y-y)/3.0+y; c[j].z=2.0*(ctrl[0].z-z)/3.0+z; c[0].x=(c[1].x+c[j].x)/2.0; c[0].y=(c[1].y+c[j].y)/2.0; c[0].z=(c[1].z+c[j].z)/2.0; j=3; for (i=0; i<cnt-2; i++) { c[j].x=(c[j-1].x+c[j+1].x)/2.0; c[j].y=(c[j-1].y+c[j+1].y)/2.0; c[j].z=(c[j-1].z+c[j+1].z)/2.0; j+=3; } c[j].x=c[0].x; c[j].y=c[0].y; c[j].z=c[0].z; } else { c=MAlloc(sizeof(CD3I32)*(cnt*3-2)); c[0].x=ctrl[0].x; c[0].y=ctrl[0].y; c[0].z=ctrl[0].z; c[cnt*3-3].x=ctrl[cnt-1].x; c[cnt*3-3].y=ctrl[cnt-1].y; c[cnt*3-3].z=ctrl[cnt-1].z; j=1; for (i=0; i<cnt-1; i++) { x=ctrl[i].x; y=ctrl[i].y; z=ctrl[i].z; c[j].x=(ctrl[i+1].x-x)/3.0+x; c[j].y=(ctrl[i+1].y-y)/3.0+y; c[j].z=(ctrl[i+1].z-z)/3.0+z; j++; c[j].x=2.0*(ctrl[i+1].x-x)/3.0+x; c[j].y=2.0*(ctrl[i+1].y-y)/3.0+y; c[j].z=2.0*(ctrl[i+1].z-z)/3.0+z; j+=2; } j=3; for (i=0; i<cnt-2; i++) { c[j].x=(c[j-1].x+c[j+1].x)/2.0; c[j].y=(c[j-1].y+c[j+1].y)/2.0; c[j].z=(c[j-1].z+c[j+1].z)/2.0; j+=3; } } for (i=0; i<cnt*3-3; i+=3) { if (!Bezier3(aux_data,&c[i],fp_plot,first)) return FALSE; first=FALSE; } Free(c); return TRUE; } #define CC_LEFT 1 #define CC_RIGHT 2 #define CC_TOP 4 #define CC_BOTTOM 8 public Bool ClipLine(I64 *_x1,I64 *_y1,I64 *_x2,I64 *_y2, I64 left,I64 top,I64 right,I64 bottom) {//Clip x1,y1 x2,y2 with left,top,right,bottom. I64 x,y,x1=*_x1,y1=*_y1,x2=*_x2,y2=*_y2, cc,cc1,cc2; if (y1>bottom) cc1=CC_BOTTOM; else if (y1<top) cc1=CC_TOP; else cc1=0; if (x1>right) cc1|=CC_RIGHT; else if (x1<left) cc1|=CC_LEFT; if (y2>bottom) cc2=CC_BOTTOM; else if (y2<top) cc2=CC_TOP; else cc2=0; if (x2>right) cc2|=CC_RIGHT; else if (x2<left) cc2|=CC_LEFT; while (TRUE) { if (!(cc1|cc2)) return TRUE; if (cc1&cc2) return FALSE; if (cc1) cc=cc1; else cc=cc2; if (cc&CC_BOTTOM) { x=x1+(x2-x1)*(bottom-y1)/(y2-y1); y=bottom; } else if (cc&CC_TOP) { x=x1+(x2-x1)*(top-y1)/(y2-y1); y=top; } else if (cc&CC_RIGHT) { y=y1+(y2-y1)*(right-x1)/(x2-x1); x=right; } else { y=y1+(y2-y1)*(left-x1)/(x2-x1); x=left; } if (cc==cc1) { *_x1=x1=x; *_y1=y1=y; if (y1>bottom) cc1=CC_BOTTOM; else if (y1<top) cc1=CC_TOP; else cc1=0; if (x1>right) cc1|=CC_RIGHT; else if (x1<left) cc1|=CC_LEFT; } else { *_x2=x2=x; *_y2=y2=y; if (y2>bottom) cc2=CC_BOTTOM; else if (y2<top) cc2=CC_TOP; else cc2=0; if (x2>right) cc2|=CC_RIGHT; else if (x2<left) cc2|=CC_LEFT; } } }