Team Ai
Datasetpublic

hschumann2/TempleOS-Source-Code

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes847downloads
GrMath.txt807 linesDownload Raw Back to Gr
1 2#help_index "Graphics/Math"3 4public I64 gr_x_offsets[8]={-1, 0, 1,-1,1,-1,0,1},5           gr_y_offsets[8]={-1,-1,-1, 0,0, 1,1,1},6          gr_x_offsets2[4]={ 0,-1, 1, 0},7          gr_y_offsets2[4]={-1, 0, 0, 1};8 9public Bool Line(U8 *aux_data,I64 x1,I64 y1,I64 z1,I64 x2,I64 y2,I64 z2,10        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),I64 step=1,I64 start=0)11{//Step through line segment calling callback.12//Uses fixed-point.13  I64 i,j,d,dx=x2-x1,dy=y2-y1,dz=z2-z1,_x,_y,_z,14        adx=AbsI64(dx),ady=AbsI64(dy),adz=AbsI64(dz);15  Bool first=TRUE;16  if (adx>=ady) {17    if (adx>=adz) {18      if (d=adx) {19        if (dx>=0)20          dx=0x100000000;21        else22          dx=-0x100000000;23        dy=dy<<32/d;24        dz=dz<<32/d;25      }26    } else {27      if (d=adz) {28        dx=dx<<32/d;29        dy=dy<<32/d;30        if (dz>=0)31          dz=0x100000000;32        else33          dz=-0x100000000;34      }35    }36  } else {37    if (ady>=adz) {38      if (d=ady) {39        dx=dx<<32/d;40        if (dy>=0)41          dy=0x100000000;42        else43          dy=-0x100000000;44        dz=dz<<32/d;45      }46    } else {47      if (d=adz) {48        dx=dx<<32/d;49        dy=dy<<32/d;50        if (dz>=0)51          dz=0x100000000;52        else53          dz=-0x100000000;54      }55    }56  }57  x1<<=32; y1<<=32; z1<<=32;58  for (j=0;j<start;j++) {59    x1+=dx; y1+=dy; z1+=dz;60  }61  if (step!=1 && step!=0) {62    dx*=step;63    dy*=step;64    dz*=step;65    d/=step;66  }67  for (i=start;i<=d;i++) {68    if ((_x!=x1.i32[1] || _y!=y1.i32[1] || _z!=z1.i32[1] || first) &&69          !(*fp_plot)(aux_data,x1.i32[1],y1.i32[1],z1.i32[1]))70      return FALSE;71    first=FALSE;72    _x=x1.i32[1]; _y=y1.i32[1]; _z=z1.i32[1];73    x1+=dx; y1+=dy; z1+=dz;74  }75  if (step==1 && (_x!=x2||_y!=y2||_z!=z2) && !(*fp_plot)(aux_data,x2,y2,z2))76    return FALSE;77  return TRUE;78}79 80#help_index "Graphics/Math/3D Transformation"81public I64 *Mat4x4MulMat4x4Equ(I64 *dst,I64 *m1,I64 *m2)82{//Multiply 4x4 matrices and store in dst. Uses fixed-point.83//Conceptually, the transform m1 is applied after m284  I64 i,j,k;85  F64 sum;86  for (i=0;i<4;i++) {87    for (j=0;j<4;j++) {88      sum=0;89      for (k=0;k<4;k++)90        sum+=ToF64(m1[k+4*j])*ToF64(m2[i+4*k]);91      dst[i+4*j]=sum/GR_SCALE;92    }93  }94  return dst;95}96 97public I64 *Mat4x4MulMat4x4New(I64 *m1,I64 *m2,CTask *mem_task=NULL)98{//Multiply 4x4 matrices. Return MAlloced matrix. Uses fixed-point.99//Conceptually, the transform m1 is applied after m2100  return Mat4x4MulMat4x4Equ(MAlloc(sizeof(I64)*16,mem_task),m1,m2);101}102 103public I64 *Mat4x4Equ(I64 *dst,I64 *src)104{//Copy 4x4 Rot matrix.105  MemCpy(dst,src,sizeof(I64)*16);106  return dst;107}108 109public I64 *Mat4x4New(I64 *src,CTask *mem_task=NULL)110{//Return MAlloced copy of 4x4 Rot matrix.111  return Mat4x4Equ(MAlloc(sizeof(I64)*16,mem_task),src);112}113 114public I64 *Mat4x4RotX(I64 *m,F64 phi)115{//Rot matrix about X axis. Uses fixed-point.116  F64 my_cos=Cos(phi)*GR_SCALE,my_sin=Sin(phi)*GR_SCALE;117  I64 r[16],r2[16];118  MemSet(r,0,sizeof(r));119  r[5]=my_cos;120  r[10]=my_cos;121  r[9]=my_sin;122  r[6]=-my_sin;123  r[0]=GR_SCALE;124  r[15]=GR_SCALE;125  return Mat4x4Equ(m,Mat4x4MulMat4x4Equ(r2,r,m));126}127 128public I64 *Mat4x4RotY(I64 *m,F64 omega)129{//Rot matrix about Y axis. Uses fixed-point.130  F64 my_cos=Cos(omega)*GR_SCALE,my_sin=Sin(omega)*GR_SCALE;131  I64 r[16],r2[16];132  MemSet(r,0,sizeof(r));133  r[0]=my_cos;134  r[10]=my_cos;135  r[8]=-my_sin;136  r[2]=my_sin;137  r[5]=GR_SCALE;138  r[15]=GR_SCALE;139  return Mat4x4Equ(m,Mat4x4MulMat4x4Equ(r2,r,m));140}141 142public I64 *Mat4x4RotZ(I64 *m,F64 theta)143{//Rot matrix about Z axis. Uses fixed-point.144  F64 my_cos=Cos(theta)*GR_SCALE,my_sin=Sin(theta)*GR_SCALE;145  I64 r[16],r2[16];146  MemSet(r,0,sizeof(r));147  r[0]=my_cos;148  r[5]=my_cos;149  r[4]=my_sin;150  r[1]=-my_sin;151  r[10]=GR_SCALE;152  r[15]=GR_SCALE;153  return Mat4x4Equ(m,Mat4x4MulMat4x4Equ(r2,r,m));154}155 156public I64 *Mat4x4Scale(I64 *m,F64 s)157{//Scale 4x4 matrix by value.158  I64 i;159  for (i=0;i<16;i++)160    m[i]*=s;161  return m;162}163 164public U0 DCThickScale(CDC *dc=gr.dc)165{//Scale device context's thick by norm of transformation.166  I64 d;167  if (dc->flags&DCF_TRANSFORMATION) {168    if (dc->thick) {169      d=dc->thick*dc->r_norm+0x80000000; //Round170      dc->thick=d.i32[1];171      if (dc->thick<1)172        dc->thick=1;173    }174  }175}176 177public I64 *Mat4x4TranslationEqu(I64 *r,I64 x,I64 y,I64 z)178{//Set translation values in 4x4 matrix. Uses fixed-point.179  r[0*4+3]=x<<32;180  r[1*4+3]=y<<32;181  r[2*4+3]=z<<32;182  r[3*4+3]=GR_SCALE;183  return r;184}185 186public I64 *Mat4x4TranslationAdd(I64 *r,I64 x,I64 y,I64 z)187{//Add translation to 4x4 matrix. Uses fixed-point.188  r[0*4+3]+=x<<32;189  r[1*4+3]+=y<<32;190  r[2*4+3]+=z<<32;191  r[3*4+3]=GR_SCALE;192  return r;193}194 195public Bool DCSymmetrySet(CDC *dc=gr.dc,I64 x1,I64 y1,I64 x2,I64 y2)196{//2D. Set device context's symmetry.197  F64 d;198  if (y1==y2 && x1==x2)199    return FALSE;200  dc->sym.snx=y2-y1;201  dc->sym.sny=x1-x2;202  dc->sym.snz=0;203  if (d=Sqrt(SqrI64(dc->sym.snx)+204        SqrI64(dc->sym.sny)+205        SqrI64(dc->sym.snz))) {206    d=GR_SCALE/d;207    dc->sym.snx *= d;208    dc->sym.sny *= d;209    dc->sym.snz *= d;210  }211  dc->sym.sx=x1;212  dc->sym.sy=y1;213  dc->sym.sz=0;214  return TRUE;215}216 217public Bool DCSymmetry3Set(CDC *dc=gr.dc,I64 x1,I64 y1,I64 z1,218        I64 x2,I64 y2,I64 z2,I64 x3,I64 y3,I64 z3)219{//3D. Set device context's symmetry.220  F64 d,x,y,z,xx,yy,zz;221  I64 xx1,yy1,zz1,xx2,yy2,zz2,*r;222  xx1=x1-x2; yy1=y1-y2; zz1=z1-z2;223  xx2=x3-x2; yy2=y3-y2; zz2=z3-z2;224  if (!xx1 && !yy1 && !zz1 ||225        !xx2 && !yy2 && !zz2 ||226        xx1==xx2 && yy1==yy2 && zz1==zz2)227    return FALSE;228 229  x=yy1*zz2-zz1*yy2;230  y=-xx1*zz2+zz1*xx2;231  z=xx1*yy2-yy1*xx2;232  if (dc->flags & DCF_TRANSFORMATION) {233    r=dc->r;234    xx=x*r[0]+y*r[1]+z*r[2];235    yy=x*r[4]+y*r[5]+z*r[6];236    zz=x*r[8]+y*r[9]+z*r[10];237    x=xx; y=yy; z=zz;238  }239  if (d=Sqrt(Sqr(x)+Sqr(y)+Sqr(z))) {240    d=GR_SCALE/d;241    dc->sym.snx = d*x;242    dc->sym.sny = d*y;243    dc->sym.snz = d*z;244  }245  if (dc->flags & DCF_TRANSFORMATION)246    (*dc->transform)(dc,&x1,&y1,&z1);247  dc->sym.sx=x1;248  dc->sym.sy=y1;249  dc->sym.sz=z1;250  return TRUE;251}252 253public U0 DCReflect(CDC *dc,I64 *_x,I64 *_y,I64 *_z)254{//Reflect 3D point about device context's symmetry. Uses fixed-point.255  I64 x=*_x<<32,y=*_y<<32,z=*_z<<32,256        xx=*_x-dc->sym.sx,yy=*_y-dc->sym.sy,zz=*_z-dc->sym.sz,257        d=(xx*dc->sym.snx+yy*dc->sym.sny+zz*dc->sym.snz)>>16,258        xn,yn,zn,xx2,yy2,zz2;259  xn=d*dc->sym.snx>>15;260  yn=d*dc->sym.sny>>15;261  zn=d*dc->sym.snz>>15;262  xx=x-xn;263  yy=y-yn;264  zz=z-zn;265  xx2=x+xn;266  yy2=y+yn;267  zz2=z+zn;268  if (SqrI64(xx>>16 -dc->sym.sx<<16)+269        SqrI64(yy>>16 -dc->sym.sy<<16)+270        SqrI64(zz>>16 -dc->sym.sz<<16)<271        SqrI64(xx2>>16-dc->sym.sx<<16)+272        SqrI64(yy2>>16-dc->sym.sy<<16)+273        SqrI64(zz2>>16-dc->sym.sz<<16)) {274    *_x=xx.i32[1]; *_y=yy.i32[1]; *_z=zz.i32[1];275  } else {276    *_x=xx2.i32[1]; *_y=yy2.i32[1]; *_z=zz2.i32[1];277  }278}279 280#help_index "Graphics/Math"281#define GR_SCALE1_BITS  24282#define GR_SCALE2_BITS  8283public Bool Circle(U8 *aux_data,I64 cx,I64 cy,I64 cz,I64 radius,284        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),285        I64 step=1,F64 start_radians=0,F64 len_radians=2*pi)286{//Step through circle arc calling callback.287  I64 i,j,len=Ceil(len_radians*radius),288        x,y,x1,y1,s1,s2,c;289  F64 t;290  if (radius<=0||!step) return TRUE;291  t=1.0/radius;292  c=1<<GR_SCALE1_BITS*Cos(t);293  if (step<0) {294    step=-step;295    s2=1<<GR_SCALE1_BITS*Sin(t);296    s1=-s2;297  } else {298    s1=1<<GR_SCALE1_BITS*Sin(t);299    s2=-s1;300  }301  if (start_radians) {302    x=radius*Cos(start_radians);303    y=-radius*Sin(start_radians);304  } else {305    x=radius;306    y=0;307  }308  x<<=GR_SCALE2_BITS;309  y<<=GR_SCALE2_BITS;310  for (i=0;i<=len;i+=step) {311    if (!(*fp_plot)(aux_data,cx+x>>GR_SCALE2_BITS,cy+y>>GR_SCALE2_BITS,cz))312      return FALSE;313    for (j=0;j<step;j++) {314      x1=(c*x+s1*y)>>GR_SCALE1_BITS;315      y1=(s2*x+c*y)>>GR_SCALE1_BITS;316      x=x1; y=y1;317    }318  }319  return TRUE;320}321 322public Bool Ellipse(U8 *aux_data,I64 cx,I64 cy,I64 cz,323        I64 x_radius,I64 y_radius,Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),324        F64 rot_angle=0,I64 step=1,F64 start_radians=0,F64 len_radians=2*pi)325{//Step through ellipse arc calling callback.326  I64 i,j,len,327        x,y,_x,_y,x1,y1,x2,y2, s1,s2,c, s12,s22,c2;328  F64 t;329  Bool first=TRUE;330  if (x_radius<=0 || y_radius<=0 || !step)331    return TRUE;332  if (x_radius>=y_radius) {333    t=1.0/x_radius;334    len=Ceil(len_radians*x_radius);335  } else {336    t=1.0/y_radius;337    len=Ceil(len_radians*y_radius);338  }339 340  c=1<<GR_SCALE1_BITS*Cos(t);341  if (step<0) {342    step=-step;343    s2=1<<GR_SCALE1_BITS*Sin(t);344    s1=-s2;345  } else {346    s1=1<<GR_SCALE1_BITS*Sin(t);347    s2=-s1;348  }349 350  c2=1<<GR_SCALE1_BITS*Cos(rot_angle);351  s12=1<<GR_SCALE1_BITS*Sin(rot_angle);352  s22=-s12;353 354  if (start_radians) {355    x=x_radius*Cos(start_radians);356    y=-x_radius*Sin(start_radians);357  } else {358    x=x_radius;359    y=0;360  }361  x<<=GR_SCALE2_BITS;362  y<<=GR_SCALE2_BITS;363  x2=x;364  y2=y;365 366  y1=y2*y_radius/x_radius;367  x=(c2*x2+s12*y1)>>GR_SCALE1_BITS;368  y=(s22*x2+c2*y1)>>GR_SCALE1_BITS;369 370  for (i=0;i<=len;i+=step) {371    if ((x>>GR_SCALE2_BITS!=_x || y>>GR_SCALE2_BITS!=_y || first) &&372          !(*fp_plot)(aux_data,cx+x>>GR_SCALE2_BITS,cy+y>>GR_SCALE2_BITS,cz))373      return FALSE;374 375    _x=x>>GR_SCALE2_BITS; _y=y>>GR_SCALE2_BITS; first=FALSE;376    for (j=0;j<step;j++) {377      x1=(c*x2+s1*y2)>>GR_SCALE1_BITS;378      y1=(s2*x2+c*y2)>>GR_SCALE1_BITS;379      x2=x1;380      y2=y1;381      y1=y1*y_radius/x_radius;382      x=(c2*x1+s12*y1)>>GR_SCALE1_BITS;383      y=(s22*x1+c2*y1)>>GR_SCALE1_BITS;384    }385  }386  return TRUE;387}388 389public Bool RegPoly(U8 *aux_data,I64 cx,I64 cy,I64 cz,390        I64 x_radius,I64 y_radius,I64 sides,391        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),392        F64 rot_angle=0,I64 step=1,F64 start_radians=0,F64 len_radians=2*pi)393{//Step through regular polygon calling callback.394  I64 i,n,x,y,x1,y1,x2,y2,395        xx1,yy1,xx2,yy2,396        s1,s2,c, s12,s22,c2;397  F64 angle_step;398 399  if (sides<=0 || x_radius<=0 || y_radius<=0)400    return TRUE;401 402  angle_step=2*pi/sides;403  n=len_radians*sides/(2*pi);404 405  s1=1<<GR_SCALE1_BITS*Sin(angle_step);406  s2=-s1;407  c=1<<GR_SCALE1_BITS*Cos(angle_step);408 409  s12=1<<GR_SCALE1_BITS*Sin(rot_angle);410  s22=-s12;411  c2=1<<GR_SCALE1_BITS*Cos(rot_angle);412 413  if (start_radians) {414    x=x_radius*Cos(start_radians);415    y=-x_radius*Sin(start_radians);416  } else {417    x=x_radius;418    y=0;419  }420  x<<=GR_SCALE2_BITS;421  y<<=GR_SCALE2_BITS;422  x2=x;423  y2=y;424 425  y1=y2*y_radius/x_radius;426  x=(c2*x2+s12*y1)>>GR_SCALE1_BITS;427  y=(s22*x2+c2*y1)>>GR_SCALE1_BITS;428 429  xx1=cx+x>>GR_SCALE2_BITS;430  yy1=cy+y>>GR_SCALE2_BITS;431  for (i=0;i<n;i++) {432    x1=(c*x2+s1*y2)>>GR_SCALE1_BITS;433    y1=(s2*x2+c*y2)>>GR_SCALE1_BITS;434    x2=x1;435    y2=y1;436    y1=y1*y_radius/x_radius;437    x=(c2*x1+s12*y1)>>GR_SCALE1_BITS;438    y=(s22*x1+c2*y1)>>GR_SCALE1_BITS;439    xx2=cx+x>>GR_SCALE2_BITS;440    yy2=cy+y>>GR_SCALE2_BITS;441    if (!Line(aux_data,xx1,yy1,cz,xx2,yy2,cz,fp_plot,step))442      return FALSE;443    xx1=xx2; yy1=yy2;444  }445  return TRUE;446}447 448#help_index "Graphics/Data Types/D3I32;Math/Data Types/D3I32;Data Types/D3I32"449public F64 D3I32Dist(CD3I32 *p1,CD3I32 *p2)450{//Distance451  return Sqrt(SqrI64(p1->x-p2->x)+SqrI64(p1->y-p2->y)+SqrI64(p1->z-p2->z));452}453 454public I64 D3I32DistSqr(CD3I32 *p1,CD3I32 *p2)455{//Distance Squared456  return SqrI64(p1->x-p2->x)+SqrI64(p1->y-p2->y)+SqrI64(p1->z-p2->z);457}458 459public F64 D3I32Norm(CD3I32 *p)460{//Norm461  return Sqrt(SqrI64(p->x)+SqrI64(p->y)+SqrI64(p->z));462}463 464public I64 D3I32NormSqr(CD3I32 *p)465{//Norm Squared466  return SqrI64(p->x)+SqrI64(p->y)+SqrI64(p->z);467}468 469#help_index "Graphics/Math"470public Bool Bezier2(U8 *aux_data,CD3I32 *ctrl,471        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool first=TRUE)472{//Go in 2nd order bezier calling callback.473  I64 x,y,z,xx,yy,zz,dx,dy,dz,d_max;474  F64 x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z,475        x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0,476        x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0,477        t,d=D3I32Dist(&ctrl[0],&ctrl[1])+478        D3I32Dist(&ctrl[1],&ctrl[2])+479        D3I32Dist(&ctrl[2],&ctrl[0]),480        s=0.5/d,t1,t2;481  xx=x0; yy=y0; zz=z0;482  if (first && !(*fp_plot)(aux_data,xx,yy,zz))483    return FALSE;484  for (t=0.0;t<=1.0;t+=s) {485    t1=t*(1.0-t);486    t2=t*t;487    x=x0+x1*t1+x2*t2;488    y=y0+y1*t1+y2*t2;489    z=z0+z1*t1+z2*t2;490    dx=AbsI64(x-xx);491    dy=AbsI64(y-yy);492    dz=AbsI64(z-zz);493    if (dx>dy)494      d_max=dx;495    else496      d_max=dy;497    if (dz>d_max)498      d_max=dz;499    if (!d_max)500      s*=1.1;501    else {502      s*=0.9;503      if (!(*fp_plot)(aux_data,x,y,z))504        return FALSE;505      xx=x;yy=y;zz=z;506    }507  }508  x=ctrl[2].x; y=ctrl[2].y; z=ctrl[2].z;509  if ((xx!=x || yy!=y || zz!=z) &&510        !(*fp_plot)(aux_data,x,y,z))511    return FALSE;512  return TRUE;513}514 515public Bool Bezier3(U8 *aux_data,CD3I32 *ctrl,516        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool first=TRUE)517{//Go in 3rd order bezier calling callback.518  I64 x,y,z,xx,yy,zz,dx,dy,dz,d_max;519  F64 x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z,520        x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0,521        x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0,522        x3=ctrl[3].x-x0,y3=ctrl[3].y-y0,z3=ctrl[3].z-z0,523        t,d=D3I32Dist(&ctrl[0],&ctrl[1])+524        D3I32Dist(&ctrl[1],&ctrl[2])+525        D3I32Dist(&ctrl[2],&ctrl[3])+526        D3I32Dist(&ctrl[3],&ctrl[0]),527        s=0.5/d,nt,t1,t2,t3;528  xx=x0; yy=y0; zz=z0;529  if (first && !(*fp_plot)(aux_data,xx,yy,zz))530    return FALSE;531  for (t=0.0;t<=1.0;t+=s) {532    nt=1.0-t;533    t1=t*nt*nt;534    t2=t*t*nt;535    t3=t*t*t;536    x=x0+x1*t1+x2*t2+x3*t3;537    y=y0+y1*t1+y2*t2+y3*t3;538    z=z0+z1*t1+z2*t2+z3*t3;539    dx=AbsI64(x-xx);540    dy=AbsI64(y-yy);541    dz=AbsI64(z-zz);542    if (dx>dy)543      d_max=dx;544    else545      d_max=dy;546    if (dz>d_max)547      d_max=dz;548    if (!d_max)549      s*=1.1;550    else {551      s*=0.9;552      if (!(*fp_plot)(aux_data,x,y,z))553        return FALSE;554      xx=x;yy=y;zz=z;555    }556  }557  x=ctrl[3].x; y=ctrl[3].y; z=ctrl[3].z;558  if ((xx!=x || yy!=y || zz!=z) &&559        !(*fp_plot)(aux_data,x,y,z))560    return FALSE;561  return TRUE;562}563 564public Bool BSpline2(U8 *aux_data,CD3I32 *ctrl,I64 cnt,565        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool closed=FALSE)566{//Go in 2nd order spline calling callback.567  I64 i,j;568  CD3I32 *c;569  Bool first;570  if (cnt<3) return FALSE;571  first=TRUE;572  if (closed) {573    cnt++;574    c=MAlloc(sizeof(CD3I32)*(cnt*2-1));575    j=1;576    for (i=0;i<cnt-2;i++) {577      c[j].x=(ctrl[i].x+ctrl[i+1].x)/2.0;578      c[j].y=(ctrl[i].y+ctrl[i+1].y)/2.0;579      c[j].z=(ctrl[i].z+ctrl[i+1].z)/2.0;580      j+=2;581    }582    c[j].x=(ctrl[0].x+ctrl[cnt-2].x)/2.0;583    c[j].y=(ctrl[0].y+ctrl[cnt-2].y)/2.0;584    c[j].z=(ctrl[0].z+ctrl[cnt-2].z)/2.0;585 586    c[0].x=(c[1].x+c[j].x)/2.0;587    c[0].y=(c[1].y+c[j].y)/2.0;588    c[0].z=(c[1].z+c[j].z)/2.0;589    j=2;590    for (i=0;i<cnt-2;i++) {591      c[j].x=(c[j-1].x+c[j+1].x)/2.0;592      c[j].y=(c[j-1].y+c[j+1].y)/2.0;593      c[j].z=(c[j-1].z+c[j+1].z)/2.0;594      j+=2;595    }596    c[j].x=c[0].x;597    c[j].y=c[0].y;598    c[j].z=c[0].z;599  } else {600    c=MAlloc(sizeof(CD3I32)*(cnt*2-1));601    c[0].x=ctrl[0].x;602    c[0].y=ctrl[0].y;603    c[0].z=ctrl[0].z;604    c[cnt*2-2].x=ctrl[cnt-1].x;605    c[cnt*2-2].y=ctrl[cnt-1].y;606    c[cnt*2-2].z=ctrl[cnt-1].z;607    j=1;608    for (i=0;i<cnt-1;i++) {609      c[j].x=(ctrl[i].x+ctrl[i+1].x)/2.0;610      c[j].y=(ctrl[i].y+ctrl[i+1].y)/2.0;611      c[j].z=(ctrl[i].z+ctrl[i+1].z)/2.0;612      j+=2;613    }614    j=2;615    for (i=0;i<cnt-2;i++) {616      c[j].x=(c[j-1].x+c[j+1].x)/2.0;617      c[j].y=(c[j-1].y+c[j+1].y)/2.0;618      c[j].z=(c[j-1].z+c[j+1].z)/2.0;619      j+=2;620    }621  }622  for (i=0;i<cnt*2-2;i+=2) {623    if (!Bezier2(aux_data,&c[i],fp_plot,first))624      return FALSE;625    first=FALSE;626  }627  Free(c);628  return TRUE;629}630 631public Bool BSpline3(U8 *aux_data,CD3I32 *ctrl,I64 cnt,632        Bool (*fp_plot)(U8 *aux,I64 x,I64 y,I64 z),Bool closed=FALSE)633{//Go in 3rd order spline calling callback.634  I64 i,j;635  F64 x,y,z;636  CD3I32 *c;637  Bool first;638  if (cnt<3) return FALSE;639  first=TRUE;640  if (closed) {641    cnt++;642    c=MAlloc(sizeof(CD3I32)*(cnt*3-2));643    j=1;644    for (i=0;i<cnt-2;i++) {645      x=ctrl[i].x;646      y=ctrl[i].y;647      z=ctrl[i].z;648      c[j].x=(ctrl[i+1].x-x)/3.0+x;649      c[j].y=(ctrl[i+1].y-y)/3.0+y;650      c[j].z=(ctrl[i+1].z-z)/3.0+z;651      j++;652      c[j].x=2.0*(ctrl[i+1].x-x)/3.0+x;653      c[j].y=2.0*(ctrl[i+1].y-y)/3.0+y;654      c[j].z=2.0*(ctrl[i+1].z-z)/3.0+z;655      j+=2;656    }657    x=ctrl[cnt-2].x;658    y=ctrl[cnt-2].y;659    z=ctrl[cnt-2].z;660    c[j].x=(ctrl[0].x-x)/3.0+x;661    c[j].y=(ctrl[0].y-y)/3.0+y;662    c[j].z=(ctrl[0].z-z)/3.0+z;663    j++;664    c[j].x=2.0*(ctrl[0].x-x)/3.0+x;665    c[j].y=2.0*(ctrl[0].y-y)/3.0+y;666    c[j].z=2.0*(ctrl[0].z-z)/3.0+z;667 668    c[0].x=(c[1].x+c[j].x)/2.0;669    c[0].y=(c[1].y+c[j].y)/2.0;670    c[0].z=(c[1].z+c[j].z)/2.0;671 672    j=3;673    for (i=0;i<cnt-2;i++) {674      c[j].x=(c[j-1].x+c[j+1].x)/2.0;675      c[j].y=(c[j-1].y+c[j+1].y)/2.0;676      c[j].z=(c[j-1].z+c[j+1].z)/2.0;677      j+=3;678    }679    c[j].x=c[0].x;680    c[j].y=c[0].y;681    c[j].z=c[0].z;682  } else {683    c=MAlloc(sizeof(CD3I32)*(cnt*3-2));684    c[0].x=ctrl[0].x;685    c[0].y=ctrl[0].y;686    c[0].z=ctrl[0].z;687    c[cnt*3-3].x=ctrl[cnt-1].x;688    c[cnt*3-3].y=ctrl[cnt-1].y;689    c[cnt*3-3].z=ctrl[cnt-1].z;690    j=1;691    for (i=0;i<cnt-1;i++) {692      x=ctrl[i].x;693      y=ctrl[i].y;694      z=ctrl[i].z;695      c[j].x=(ctrl[i+1].x-x)/3.0+x;696      c[j].y=(ctrl[i+1].y-y)/3.0+y;697      c[j].z=(ctrl[i+1].z-z)/3.0+z;698      j++;699      c[j].x=2.0*(ctrl[i+1].x-x)/3.0+x;700      c[j].y=2.0*(ctrl[i+1].y-y)/3.0+y;701      c[j].z=2.0*(ctrl[i+1].z-z)/3.0+z;702      j+=2;703    }704    j=3;705    for (i=0;i<cnt-2;i++) {706      c[j].x=(c[j-1].x+c[j+1].x)/2.0;707      c[j].y=(c[j-1].y+c[j+1].y)/2.0;708      c[j].z=(c[j-1].z+c[j+1].z)/2.0;709      j+=3;710    }711  }712  for (i=0;i<cnt*3-3;i+=3) {713    if (!Bezier3(aux_data,&c[i],fp_plot,first))714      return FALSE;715    first=FALSE;716  }717  Free(c);718  return TRUE;719}720 721#define CC_LEFT         1722#define CC_RIGHT        2723#define CC_TOP          4724#define CC_BOTTOM       8725 726public Bool ClipLine(I64 *_x1,I64 *_y1,I64 *_x2,I64 *_y2,727        I64 left,I64 top,I64 right,I64 bottom)728{//Clip x1,y1 x2,y2 with left,top,right,bottom.729  I64 x,y,x1=*_x1,y1=*_y1,x2=*_x2,y2=*_y2,730        cc,cc1,cc2;731  if (y1>bottom)732    cc1=CC_BOTTOM;733  else if (y1<top)734    cc1=CC_TOP;735  else736    cc1=0;737  if (x1>right)738    cc1|=CC_RIGHT;739  else if (x1<left)740    cc1|=CC_LEFT;741 742  if (y2>bottom)743    cc2=CC_BOTTOM;744  else if (y2<top)745    cc2=CC_TOP;746  else747    cc2=0;748  if (x2>right)749    cc2|=CC_RIGHT;750  else if (x2<left)751    cc2|=CC_LEFT;752 753  while (TRUE) {754    if (!(cc1|cc2))755      return TRUE;756    if (cc1&cc2)757      return FALSE;758 759    if (cc1)760      cc=cc1;761    else762      cc=cc2;763 764    if (cc&CC_BOTTOM) {765      x=x1+(x2-x1)*(bottom-y1)/(y2-y1);766      y=bottom;767    } else if (cc&CC_TOP) {768      x=x1+(x2-x1)*(top-y1)/(y2-y1);769      y=top;770    } else if (cc&CC_RIGHT) {771      y=y1+(y2-y1)*(right-x1)/(x2-x1);772      x=right;773    } else {774      y=y1+(y2-y1)*(left-x1)/(x2-x1);775      x=left;776    }777 778    if (cc==cc1) {779      *_x1=x1=x;780      *_y1=y1=y;781      if (y1>bottom)782        cc1=CC_BOTTOM;783      else if (y1<top)784        cc1=CC_TOP;785      else786        cc1=0;787      if (x1>right)788        cc1|=CC_RIGHT;789      else if (x1<left)790        cc1|=CC_LEFT;791    } else {792      *_x2=x2=x;793      *_y2=y2=y;794      if (y2>bottom)795        cc2=CC_BOTTOM;796      else if (y2<top)797        cc2=CC_TOP;798      else799        cc2=0;800      if (x2>right)801        cc2|=CC_RIGHT;802      else if (x2<left)803        cc2|=CC_LEFT;804    }805  }806}807