00001 
00010 #include "graph.h"
00011 #include "jbxl_state.h"
00012 
00013 
00025 int  get_idat(WSGraph gd, int xx, int yy, int zz)
00026 {
00027     int  ret = 0;
00028 
00029     if (xx>0&&yy>0&&zz>0&&xx<gd.xs&&yy<gd.ys&&zz<gd.zs) {
00030         ret = gd.gp[zz*gd.xs*gd.ys + yy*gd.xs + xx];
00031     }
00032     return  ret;
00033 }
00034 
00035 
00036 
00049 int   get_wdat(WSGraph gd, double xx, double yy, double zz, IRBound rb)
00050 {
00051     int  ix, iy, iz;
00052     int  ret = 0;
00053 
00054     if (chk_RZxy()) zz = zz*RZxy;  
00055 
00056     ix = (int)(xx+0.5) - rb.xmin;
00057     iy = (int)(yy+0.5) - rb.ymin;
00058     iz = (int)(zz+0.5) - rb.zmin;
00059 
00060     if (ix>=0&&ix<gd.xs&&iy>=0&&iy<gd.ys&&iz>=0&&iz<gd.zs){ 
00061         ret = gd.gp[iz*gd.xs*gd.ys + iy*gd.xs + ix];
00062     }
00063     return ret;
00064 }
00065 
00066 
00067 
00079 int  get_bdat(BSGraph gd, int xx, int yy, int zz)
00080 {
00081     int  ret = 0;
00082 
00083     if (xx>0&&yy>0&&zz>0&&xx<gd.xs&&yy<gd.ys&&zz<gd.zs) {
00084         ret = (int)gd.gp[zz*gd.xs*gd.ys + yy*gd.xs + xx];
00085     }
00086     return  ret;
00087 }
00088 
00089 
00090 
00101 void  set_idat(WSGraph gd, int ix, int iy, int iz, int cc)
00102 {
00103     if (ix>=0&&ix<gd.xs&&iy>=0&&iy<gd.ys&&iz>=0&&iz<gd.zs){
00104         gd.gp[iz*gd.xs*gd.ys + iy*gd.xs + ix] = cc;
00105     }
00106 }
00107 
00108 
00109 
00123 void  set_wdat(WSGraph gd, double xx, double yy, double zz, int cc, IRBound rb)
00124 {
00125     int  i, j, k;
00126     int  x, y, z;
00127     int  ix, iy, iz;
00128 
00129     if (chk_RZxy()) zz = zz*RZxy;  
00130 
00131     if (rb.misc==OFF) {
00132         ix = (int)(xx+0.5) - rb.xmin;
00133         iy = (int)(yy+0.5) - rb.ymin;
00134         iz = (int)(zz+0.5) - rb.zmin;
00135 
00136         if (ix>=0&&ix<gd.xs&&iy>=0&&iy<gd.ys&&iz>=0&&iz<gd.zs){
00137             gd.gp[iz*gd.xs*gd.ys + iy*gd.xs + ix] = cc;
00138         }
00139     }
00140     else {
00141         x = (int)(xx) - rb.xmin;
00142         y = (int)(yy) - rb.ymin;
00143         z = (int)(zz) - rb.zmin;
00144 
00145         for (i=0; i<=1; i++) {
00146             for (j=0; j<=1; j++) {
00147                 for (k=0; k<=1; k++) {
00148                     ix = i + x;
00149                     iy = j + y;
00150                     iz = k + z;
00151                     if (ix>=0&&ix<gd.xs&&iy>=0&&iy<gd.ys&&iz>=0&&iz<gd.zs){
00152                         gd.gp[iz*gd.xs*gd.ys + iy*gd.xs + ix] = cc;
00153                     }
00154                 }
00155             }
00156         }
00157     }
00158     return;
00159 }
00160 
00161 
00162 
00173 void  set_bdat(BSGraph gd, int ix, int iy, int iz, int cc)
00174 {
00175     if (ix>=0&&ix<gd.xs&&iy>=0&&iy<gd.ys&&iz>=0&&iz<gd.zs){
00176         gd.gp[iz*gd.xs*gd.ys + iy*gd.xs + ix] = cc;
00177     }
00178 }
00179 
00180 
00181 
00197 void  local2world(WSGraph gd, WSGraph vp, vector ox, vector oz, vector ex, double* pcsf, double* psnf)
00198 {
00199     int  x, y, z, cx, cy, cz;
00200     double px, py, pz, xx, yy, zz;
00201     double cst, snt, csf=0.0, snf=1.0;
00202     IRBound rb;
00203 
00204     if (pcsf!=NULL && psnf!=NULL) {
00205         csf = *pcsf;
00206         snf = *psnf;
00207     }
00208 
00209     rb.xmin = rb.ymin = rb.zmin = 0;
00210     rb.misc = ON;
00211     topola(ex, &cst, &snt, &csf, &snf);
00212 
00213     for(z=0; z<vp.zs; z++) {
00214         cz = z*vp.xs*vp.ys;
00215         for(y=0; y<vp.ys; y++) {
00216             cy = cz + y*vp.xs;
00217             for(x=0; x<vp.xs; x++) {
00218                 cx = cy + x;
00219                 if(vp.gp[cx]!=0) {
00220                     px = z - oz.z;
00221                     py = oz.x - x;
00222                     pz = oz.y - y;
00223                     xx = px*snt*csf - py*snf - pz*cst*csf + ox.x;
00224                     yy = px*snt*snf + py*csf - pz*cst*snf + ox.y;
00225                     zz = px*cst              + pz*snt     + ox.z;
00226                     set_wdat(gd, xx, yy, zz, vp.gp[cx], rb);
00227                 }
00228             }
00229         }
00230     }
00231 
00232     if (pcsf!=NULL && psnf!=NULL) {
00233         *pcsf = csf;
00234         *psnf = snf;
00235     }
00236 }
00237 
00238 
00239 
00256 void  paint(WSGraph vp, int x, int y, int mn, int mx, int c, int m)
00257 {
00258     int  i, j, k, cc;
00259 
00260     if (c<=mx && c>=mn) {
00261         fprintf(stderr,"PAINT: c = %d. Not be %d< c <%d\n\n",c,mn,mx); 
00262         return;
00263     }
00264 
00265     cc = vp.gp[y*vp.xs+x];
00266     if (cc>mx || cc<mn) return;
00267 
00268     while(x>0) {
00269         if (vp.gp[y*vp.xs+x-1]>mx || vp.gp[y*vp.xs+x-1]<mn) break;
00270         x--; 
00271     }
00272     k = x;
00273 
00274     while(k<vp.xs) {
00275         if (vp.gp[y*vp.xs+k]>mx || vp.gp[y*vp.xs+k]<mn) break;
00276         vp.gp[y*vp.xs+k] = c; 
00277         k++;
00278     }
00279     k--;
00280 
00281     for (i=x; i<=k; i++){ 
00282         if (y-1>=0 && y-1<vp.ys){ 
00283             j = (y-1)*vp.xs+i;
00284             if (vp.gp[j]<=mx && vp.gp[j]>=mn) {
00285                 paint(vp, i, y-1, mn, mx, c, m);
00286             }
00287 
00288             if (Xabs(m)==8) {  
00289                 if (i-1>=0) {
00290                     if (vp.gp[j-1]<=mx && vp.gp[j-1]>=mn) {
00291                         paint(vp, i-1, y-1, mn, mx, c, m);
00292                     }
00293                 }
00294                 if (i+1<vp.xs) {
00295                     if (vp.gp[j+1]<=mx && vp.gp[j+1]>=mn) {
00296                         paint(vp, i+1, y-1, mn, mx, c, m);
00297                     }
00298                 }
00299             }
00300         }
00301 
00302         if (y+1>=0 && y+1<vp.ys){
00303             j = (y+1)*vp.xs+i;
00304             if (vp.gp[j]<=mx && vp.gp[j]>=mn) {
00305                 paint(vp, i, y+1, mn, mx, c, m);
00306             }
00307 
00308             if (Xabs(m)==8) {  
00309                 if (i-1>=0) {
00310                     if (vp.gp[j-1]<=mx && vp.gp[j-1]>=mn) {
00311                         paint(vp, i-1, y+1, mn, mx, c, m);
00312                     }
00313                 }
00314                 if (i+1<vp.xs) {
00315                     if (vp.gp[j+1]<=mx && vp.gp[j+1]>=mn) {
00316                         paint(vp, i+1, y+1, mn, mx, c, m);
00317                     }
00318                 }
00319             }
00320         }
00321     }
00322     return;
00323 }
00324 
00325 
00326 
00344 void  paint3d(WSGraph vp, int x, int y, int z, int mn, int mx, int c, int m)
00345 {
00346     int  i;
00347  
00348     _paint_3d(vp, x, y, z, mn, mx, SWORDMAX, m);
00349     for (i=0; i<vp.xs*vp.ys*vp.zs; i++) {
00350         if (vp.gp[i]==SWORDMAX) vp.gp[i] = c;
00351     }
00352 }
00353 
00354 
00355 
00361 void  _paint_3d(WSGraph vp, int x, int y, int z, int mn, int mx, int c, int m)
00362 {
00363     int  i, j, ps, cc;
00364     WSGraph xp;
00365 
00366     ps  = vp.xs*vp.ys;
00367     xp.xs = vp.xs;
00368     xp.ys = vp.ys;
00369     xp.zs = 1;
00370     xp.gp = &(vp.gp[z*ps]);
00371     xp.state = vp.state;
00372 
00373     cc = xp.gp[y*xp.xs+x];
00374     if (cc>mx || cc<mn) return;
00375     paint(xp, x, y, mn, mx, c, m);
00376     if (m<0) {
00377         DEBUG_MODE fprintf(stderr,"_paint_3d: zz = %d\n",z);
00378     }
00379 
00380     for (i=0; i<ps; i++) {
00381         if (xp.gp[i]==c) {
00382             x = i%vp.xs;
00383             y = i/vp.xs;
00384             if (z-1>=0) {
00385                 j = (z-1)*ps+y*vp.xs+x;
00386                 if (vp.gp[j]<=mx && vp.gp[j]>=mn) _paint_3d(vp, x, y, z-1, mn, mx, c, m);
00387             }
00388             if (z+1<vp.zs) {
00389                 j = (z+1)*ps+y*vp.xs+x;
00390                 if (vp.gp[j]<=mx && vp.gp[j]>=mn) _paint_3d(vp, x, y, z+1, mn, mx, c, m);
00391             }
00392         }
00393     }
00394 
00395     return;
00396 }
00397 
00398 
00399 
00416 void  bline(BSGraph vp, int x1, int y1, int x2, int y2, int cc)
00417 {
00418     int  thresh=0, index;
00419     int  xunit=1;
00420     int  yunit=1;
00421     int  xdiff=x2-x1;
00422     int  ydiff=y2-y1;
00423 
00424     if (xdiff<0) {
00425         xdiff = -xdiff;
00426         xunit = -1;
00427     }
00428     if (ydiff<0) {
00429         ydiff = -ydiff;
00430         yunit = -1;
00431     }
00432 
00433     if (xdiff>ydiff) {
00434         for (index=0; index<xdiff+1; index++) {
00435             set_bdat(vp, x1, y1, 0, cc);
00436             x1 = x1 + xunit;
00437             thresh = thresh + ydiff;
00438             if (thresh>=xdiff) {
00439                 thresh = thresh - xdiff;
00440                 y1 = y1 + yunit;
00441             }
00442         }
00443     }
00444     else {
00445         for (index=0; index<ydiff+1; index++) {
00446             set_bdat(vp, x1, y1, 0, cc);
00447             y1 = y1 + yunit;
00448             thresh = thresh + xdiff;
00449             if (thresh>=ydiff) {
00450                 thresh = thresh - ydiff;
00451                 x1 = x1 + xunit;
00452             }
00453         }
00454     }
00455 }
00456 
00457 
00458 
00475 void  line(WSGraph vp, int x1, int y1, int x2, int y2, int cc)
00476 {
00477     int  thresh=0, index;
00478     int  xunit=1;
00479     int  yunit=1;
00480     int  xdiff=x2-x1;
00481     int  ydiff=y2-y1;
00482 
00483     if (xdiff<0) {
00484         xdiff = -xdiff;
00485         xunit = -1;
00486     }
00487     if (ydiff<0) {
00488         ydiff = -ydiff;
00489         yunit = -1;
00490     }
00491 
00492     if (xdiff>ydiff) {
00493         for (index=0; index<xdiff+1; index++) {
00494             set_idat(vp, x1, y1, 0, cc);
00495             x1 = x1 + xunit;
00496             thresh = thresh + ydiff;
00497             if (thresh>=xdiff) {
00498                 thresh = thresh - xdiff;
00499                 y1 = y1 + yunit;
00500             }
00501         }
00502     }
00503     else {
00504         for (index=0; index<ydiff+1; index++) {
00505             set_idat(vp, x1, y1, 0, cc);
00506             y1 = y1 + yunit;
00507             thresh = thresh + xdiff;
00508             if (thresh>=ydiff) {
00509                 thresh = thresh - ydiff;
00510                 x1 = x1 + xunit;
00511             }
00512         }
00513     }
00514 }
00515 
00516 
00517 
00536 void triangle(WSGraph vp, int x1, int y1, int x2, int y2, int x3, int y3, int cc, int mode) 
00537 {
00538     line(vp, x1, y1, x2, y2, cc);
00539     line(vp, x2, y2, x3, y3, cc);
00540     line(vp, x3, y3, x1, y1, cc);
00541 
00542     if (mode==ON) {
00543         int i, j, minx, miny, maxx, maxy;
00544         minx = maxx = x1;
00545         miny = maxy = y1;
00546         minx = Min(x2, minx);
00547         minx = Min(x3, minx);
00548         miny = Min(y2, miny);
00549         miny = Min(y3, miny);
00550         maxx = Max(x2, maxx);
00551         maxx = Max(x3, maxx);
00552         maxy = Max(y2, maxy);
00553         maxy = Max(y3, maxy);
00554     
00555         for (j=miny; j<=maxy; j++) {
00556             for (i=minx; i<=maxx; i++) {
00557                 if (isinctri(x1, y1, x2, y2, x3, y3, i, j)) Px(vp, i, j) = cc;
00558             }
00559         }
00560     }
00561     return;
00562 }
00563 
00564 
00565 
00574 int  isinctri(int x1, int y1, int x2, int y2, int x3, int y3, int xx, int yy)
00575 {
00576     int cx, cy;
00577 
00578     cx = (x1 + x2 + x3)/3;
00579     cy = (y1 + y2 + y3)/3;
00580 
00581     if (isCrossLine(x1, y1, x2, y2, xx, yy, cx, cy)<0) return FALSE;
00582     if (isCrossLine(x1, y1, x3, y3, xx, yy, cx, cy)<0) return FALSE;
00583     if (isCrossLine(x2, y2, x3, y3, xx, yy, cx, cy)<0) return FALSE;
00584     return TRUE;
00585 }
00586 
00587 
00588 
00605 void  box(WSGraph vp, int x1, int y1, int x2, int y2, int cc, int mode) 
00606 {
00607     line(vp, x1, y1, x2, y1, cc);
00608     line(vp, x2, y1, x2, y2, cc);
00609     line(vp, x2, y2, x1, y2, cc);
00610     line(vp, x1, y2, x1, y1, cc);
00611 
00612     if (mode==ON) {
00613         paint(vp, (x1+x2)/2, (y1+y2)/2, 0, cc-1, cc, 4); 
00614     }
00615     return;
00616 }
00617 
00618 
00619 
00630 void  bline3d(BSGraph gd, int x1, int y1, int z1, int x2, int y2, int z2, int cc)
00631 {
00632     int  i;
00633     int  xx, yy, zz, dx, dy, dz;
00634     int  ux=1, uy=1, uz=1;
00635     int  sx=0, sy=0, sz=0;
00636 
00637     dx = x2 - x1;
00638     dy = y2 - y1;
00639     dz = z2 - z1;
00640 
00641     if (dx<0) {
00642         dx = -dx;
00643         ux = -1;
00644     }
00645     if (dy<0) {
00646         dy = -dy;
00647         uy = -1;
00648     }
00649     if (dz<0) {
00650         dz = -dz;
00651         uz = -1;
00652     }
00653 
00654     xx = x1;
00655     yy = y1;
00656     zz = z1;
00657 
00658     set_bdat(gd, xx, yy, zz, cc);
00659     if (dx>=dy && dx>=dz) {
00660         for (i=1; i<=dx; i++) {
00661             xx = xx + ux;
00662             sy = sy + dy;
00663             sz = sz + dz;
00664             if (sy>dx) {
00665                 sy = sy - dx;
00666                 yy = yy + uy;
00667             }
00668             if (sz>dx) {
00669                 sz = sz - dx;
00670                 zz = zz + uz;
00671             }
00672             set_bdat(gd, xx, yy, zz, cc);
00673         }
00674     }
00675     else if (dy>dx && dy>=dz) {
00676         for (i=1; i<=dy; i++) {
00677             yy = yy + uy;
00678             sx = sx + dx;
00679             sz = sz + dz;
00680             if (sx>dy) {
00681                 sx = sx - dy;
00682                 xx = xx + ux;
00683             }
00684             if (sz>dy) {
00685                 sz = sz - dy;
00686                 zz = zz + uz;
00687             }
00688             set_bdat(gd, xx, yy, zz, cc);
00689         }
00690     }
00691     else {
00692         for (i=1; i<=dz; i++) {
00693             zz = zz + uz;
00694             sx = sx + dx;
00695             sy = sy + dy;
00696             if (sx>dz) {
00697                 sx = sx - dz;
00698                 xx = xx + ux;
00699             }
00700             if (sy>dz) {
00701                 sy = sy - dz;
00702                 yy = yy + uy;
00703             }
00704             set_bdat(gd, xx, yy, zz, cc);
00705         }
00706     }
00707 }
00708 
00709 
00710 
00721 void  line3d(WSGraph gd, int x1, int y1, int z1, int x2, int y2, int z2, int cc)
00722 {
00723     int  i;
00724     int  xx, yy, zz, dx, dy, dz;
00725     int  ux=1, uy=1, uz=1;
00726     int  sx=0, sy=0, sz=0;
00727 
00728     dx = x2 - x1;
00729     dy = y2 - y1;
00730     dz = z2 - z1;
00731 
00732     if (dx<0) {
00733         dx = -dx;
00734         ux = -1;
00735     }
00736     if (dy<0) {
00737         dy = -dy;
00738         uy = -1;
00739     }
00740     if (dz<0) {
00741         dz = -dz;
00742         uz = -1;
00743     }
00744 
00745     xx = x1;
00746     yy = y1;
00747     zz = z1;
00748 
00749     set_idat(gd, xx, yy, zz, cc);
00750     if (dx>=dy && dx>=dz) {
00751         for (i=1; i<=dx; i++) {
00752             xx = xx + ux;
00753             sy = sy + dy;
00754             sz = sz + dz;
00755             if (sy>dx) {
00756                 sy = sy - dx;
00757                 yy = yy + uy;
00758             }
00759             if (sz>dx) {
00760                 sz = sz - dx;
00761                 zz = zz + uz;
00762             }
00763             set_idat(gd, xx, yy, zz, cc);
00764         }
00765     }
00766     else if (dy>dx && dy>=dz) {
00767         for (i=1; i<=dy; i++) {
00768             yy = yy + uy;
00769             sx = sx + dx;
00770             sz = sz + dz;
00771             if (sx>dy) {
00772                 sx = sx - dy;
00773                 xx = xx + ux;
00774             }
00775             if (sz>dy) {
00776                 sz = sz - dy;
00777                 zz = zz + uz;
00778             }
00779             set_idat(gd, xx, yy, zz, cc);
00780         }
00781     }
00782     else {
00783         for (i=1; i<=dz; i++) {
00784             zz = zz + uz;
00785             sx = sx + dx;
00786             sy = sy + dy;
00787             if (sx>dz) {
00788                 sx = sx - dz;
00789                 xx = xx + ux;
00790             }
00791             if (sy>dz) {
00792                 sy = sy - dz;
00793                 yy = yy + uy;
00794             }
00795             set_idat(gd, xx, yy, zz, cc);
00796         }
00797     }
00798 }
00799 
00800 
00801 
00813 void  circle(WSGraph gd, int x, int y, int r, int cc, int mode)
00814 {
00815     double yy, dy, dt;
00816     int i, nn, cx;
00817     int ix, iy, ux=1;
00818     int *px, *py;
00819 
00820     if (r<=0) return;
00821 
00822     px = (int*)malloc(sizeof(int)*(r+1));
00823     py = (int*)malloc(sizeof(int)*(r+1));
00824     if (px==NULL || py==NULL) {
00825         free(px);
00826         free(py);
00827         return;
00828     }
00829 
00830     ix = 0;
00831     iy = r;
00832     yy = (double)r;
00833     nn = 0;
00834     px[0] = ix;
00835     py[0] = iy;
00836 
00837     cx = (y+iy)*gd.xs + (x+ix);
00838     gd.gp[cx] = cc;
00839     while(iy>=ix) {
00840         ix = ix + ux;
00841         dt = -ux/yy;
00842         dy = ix*dt;
00843         yy = yy + dy;
00844         iy = (int)yy;
00845 
00846         set_idat(gd, x+ix, y+iy, 0, cc);
00847         nn++;
00848         px[nn] = ix;
00849         py[nn] = iy;
00850     }
00851 
00852     for (i=0; i<=nn; i++) {
00853         ix = py[nn-i];
00854         iy = px[nn-i];
00855         set_idat(gd, x+ix, y+iy, 0, cc);
00856     }
00857 
00858     for (i=0; i<=nn; i++) {
00859         ix = py[i];
00860         iy = -px[i];
00861         set_idat(gd, x+ix, y+iy, 0, cc);
00862     }
00863 
00864     for (i=0; i<=nn; i++) {
00865         ix = px[nn-i];
00866         iy = -py[nn-i];
00867         set_idat(gd, x+ix, y+iy, 0, cc);
00868     }
00869 
00870     for (i=0; i<=nn; i++) {
00871         ix = -px[i];
00872         iy = -py[i];
00873         set_idat(gd, x+ix, y+iy, 0, cc);
00874     }
00875 
00876     for (i=0; i<=nn; i++) {
00877         ix = -py[nn-i];
00878         iy = -px[nn-i];
00879         set_idat(gd, x+ix, y+iy, 0, cc);
00880     }
00881 
00882     for (i=0; i<=nn; i++) {
00883         ix = -py[i];
00884         iy = px[i];
00885         set_idat(gd, x+ix, y+iy, 0, cc);
00886     }
00887 
00888     for (i=0; i<=nn; i++) {
00889         ix = -px[nn-i];
00890         iy = py[nn-i];
00891         set_idat(gd, x+ix, y+iy, 0, cc);
00892     }
00893 
00894     if (mode==ON) paint(gd, x, y, 0, cc-1, cc, 4);
00895 
00896     free(px);
00897     free(py);
00898 }
00899 
00900 
00901 
00914 void  circle3d(WSGraph gd, vector ox, vector ex, int rr, int cc, int mode)
00915 {
00916     vector   oz;
00917     WSGraph  vp;
00918 
00919     vp = make_WSGraph(2*rr+3, 2*rr+3, 1);
00920     if (vp.gp==NULL) return;
00921     circle(vp, rr+1, rr+1, rr, cc, mode);
00922 
00923     oz = set_vector((vp.xs-1)/2., (vp.ys-1)/2., 0.0);
00924     ex = unit_vector(ex);
00925     local2world(gd, vp, ox, oz, ex, NULL, NULL);
00926 
00927     free(vp.gp);
00928 }
00929 
00930 
00931 
00943 void  pool(WSGraph gd, vector a, vector b, int rr, int cc)
00944 {
00945     int  i, ll, cz;
00946     vector  ox, oz, ev;
00947     WSGraph vp, px;
00948 
00949     ox = sub_vector(b, a);
00950     ll = (int)(ox.n + 0.5);
00951     vp = px = make_WSGraph(2*rr+3, 2*rr+3, ll);
00952     if (vp.gp==NULL) return;
00953 
00954     for (i=0; i<vp.zs; i++) {
00955         cz = i*vp.xs*vp.ys;
00956         px.gp = &(vp.gp[cz]);
00957         circle(px, rr+1, rr+1, rr, cc, ON);
00958     }
00959     
00960     oz = set_vector((vp.xs-1)/2., (vp.ys-1)/2., 0.);
00961     ev = unit_vector(ox);
00962     local2world(gd, vp, a, oz, ev, NULL, NULL);
00963     free(vp.gp);
00964 
00965     return;
00966 }
00967 
00968 
00969 
00982 void  torus(WSGraph gd, vector ox, vector ex, int rr, int ra, int cc)
00983 {
00984     int  i, nn;
00985     double  dt, th, xx, yy, zz, sn, cs;
00986     WSGraph vp;
00987     vector  ve, vo, vz;
00988 
00989     vp = make_WSGraph(2*(rr+ra)+3, 2*(rr+ra)+3, 2*ra+3);
00990     if (vp.gp==NULL) return;
00991     nn = (int)(2*PI*(rr+ra)*2);
00992     dt = 2.0*PI/nn;
00993 
00994     zz = (vp.zs-1)/2.;
00995     for (i=0; i<nn; i++) {
00996         th = dt*i;
00997         sn = sin(th);
00998         cs = cos(th);
00999         xx = (vp.xs-1)/2. + rr*cs;
01000         yy = (vp.ys-1)/2. - rr*sn;
01001         vo = set_vector(xx, yy, zz);
01002         ve = set_vector(sn, cs, 0.0);
01003         circle3d(vp, vo, ve, ra, cc, ON);
01004     }
01005     vz = set_vector((vp.xs-1)/2., (vp.ys-1)/2., (vp.zs-1)/2.);
01006     ex = unit_vector(ex);
01007 
01008     local2world(gd, vp, ox, vz, ex, NULL, NULL);
01009     free(vp.gp);
01010     return;
01011 }
01012 
01013 
01014 
01029 void  sphere(WSGraph vp, vector a, int r, int cc, int mode)
01030 {
01031     int i, j, k, rx, nn, s = 1;
01032     double th, fi, cs, sn, cf, sf, dt;
01033     double xx, yy, zz, zc;
01034     WSGraph xp;
01035     IRBound rb;
01036  
01037     memset(&xp, 0, sizeof(WSGraph));
01038 
01039     if (mode==1) {
01040         xp.xs = vp.xs;
01041         xp.ys = vp.ys;
01042         xp.zs = 1;
01043 
01044         for (k=(int)(a.z-r+0.5); k<=(int)(a.z+r+0.5); k++) {
01045             if (k>=0 && k<vp.zs) {
01046                 xp.gp = &vp.gp[k*vp.xs*vp.ys];
01047                 rx = (int)(sqrt(r*r-(a.z-k)*(a.z-k))+0.5);
01048                 circle(xp, (int)a.x, (int)a.y, rx, cc, ON);
01049             }
01050         }   
01051     }
01052     else {
01053         rb.xmin = rb.ymin = rb.zmin = 0;
01054         rb.misc = OFF;
01055 
01056         nn = (int)(2*PI*r + 0.5)*2;
01057         dt = PI/nn;
01058         for (i=0; i<=nn; i++) {
01059             th = dt*i;
01060             sn = sin(th);
01061             cs = cos(th);
01062             zz = r*cs + a.z;
01063             zc = zz*RZxy;
01064             if (mode==-1) {
01065                 if (zc<s)        zz = s/RZxy;
01066                 if (zc>vp.zs-s-1) zz = (vp.zs-s-1)/RZxy;
01067             }
01068             for (j=0; j<=2*nn; j++) {
01069                 fi = dt*j;
01070                 cf = cos(fi);
01071                 sf = sin(fi);
01072                 xx = r*sn*cf + a.x;
01073                 yy = r*sn*sf + a.y;
01074                 if (mode==-1) {
01075                     if (xx<s)         xx = (double)s;
01076                     if (yy<s)         yy = (double)s;
01077                     if (xx>vp.xs-s-1) xx = (double)(vp.xs-s-1);
01078                     if (yy>vp.ys-s-1) yy = (double)(vp.ys-s-1);
01079                 }
01080                 set_wdat(vp, xx, yy, zz, cc, rb);
01081             }
01082         }
01083     }
01084     return;
01085 }
01086 
01087 
01088 
01097 WSGraph  x_reverse_wsg(WSGraph vp)
01098 {
01099     int  i, j, cy;
01100     WSGraph  wp;
01101 
01102     wp = make_WSGraph(vp.xs, vp.ys, 1);
01103     if (wp.gp==NULL) {
01104         memset(&wp, 0, sizeof(WSGraph));
01105         wp.state = JBXL_GRAPH_MEMORY_ERROR;
01106         return wp;
01107     }
01108 
01109     for (j=0; j<vp.ys; j++) {
01110         cy = j*vp.xs;
01111         for (i=0; i<vp.xs; i++) {
01112             wp.gp[cy +i] = vp.gp[cy + vp.xs - 1 - i];
01113         }
01114     }
01115     return wp;
01116 }
01117 
01118 
01119 
01134 void  topola(vector nv, double* cst, double* snt, double* csf, double* snf)
01135 {
01136     if (nv.n>EPS && nv.n!=1.0) {
01137         nv.x = nv.x/nv.n;
01138         nv.y = nv.y/nv.n;
01139         nv.z = nv.z/nv.n;
01140     }
01141 
01142     if (nv.z<-1.0) nv.z = -1.0;
01143     if (nv.z> 1.0) nv.z =  1.0;
01144     *cst = nv.z;
01145     *snt = sqrt(1.0-nv.z*nv.z);
01146 
01147     if (*snt<EPS) {
01148         *cst = Sign(*cst);
01149         *snt = 0.0;
01150         
01151         
01152     }
01153     else {
01154         *csf = nv.x / *snt;
01155         *snf = nv.y / *snt;
01156     }
01157     return;
01158 }
01159 
01160 
01161 
01174 WSGraph  cut_object(WSGraph vp, int cc, IRBound* rb, int blank)
01175 {
01176     int  i, j, k, cx, ax;
01177     WSGraph xp;
01178 
01179     init_IRBound(rb);
01180 
01181     for (i=0; i<vp.xs; i++) 
01182     for (j=0; j<vp.ys; j++)
01183     for (k=0; k<vp.zs; k++) {
01184         cx = vp.xs*vp.ys*k + vp.xs*j + i;
01185         if (vp.gp[cx]>=cc) {
01186             rb->xmax = Max(rb->xmax, i);
01187             rb->ymax = Max(rb->ymax, j);
01188             rb->zmax = Max(rb->zmax, k);
01189             rb->xmin = Min(rb->xmin, i);
01190             rb->ymin = Min(rb->ymin, j);
01191             rb->zmin = Min(rb->zmin, k);
01192         }
01193     }
01194 
01195     if (blank!=0) {
01196         rb->xmax += blank;
01197         rb->ymax += blank;
01198         rb->zmax += blank;
01199         rb->xmin -= blank;
01200         rb->ymin -= blank;
01201         rb->zmin -= blank;
01202         rb->xmin = Max(rb->xmin, 0);
01203         rb->ymin = Max(rb->ymin, 0);
01204         rb->zmin = Max(rb->zmin, 0);
01205         rb->zmax = Min(rb->zmax, vp.zs-1);
01206     }
01207 
01208     xp.xs = rb->xmax - rb->xmin + 1;
01209     xp.ys = rb->ymax - rb->ymin + 1;
01210     xp.zs = rb->zmax - rb->zmin + 1;
01211     xp = make_WSGraph(xp.xs, xp.ys, xp.zs);
01212     if (xp.gp==NULL) {
01213         xp.state = JBXL_GRAPH_MEMORY_ERROR;
01214         return xp;
01215     }
01216 
01217     for (i=0; i<xp.xs; i++) {
01218         for (j=0; j<xp.ys; j++) {
01219             for (k=0; k<xp.zs; k++) {
01220                 cx = xp.xs*xp.ys*k + xp.xs*j + i;
01221                 ax = vp.xs*vp.ys*(k+rb->zmin) + vp.xs*(j+rb->ymin) + (i+rb->xmin);
01222                 if (vp.gp[ax]>=cc) xp.gp[cx] = vp.gp[ax];
01223             }
01224         }
01225     }
01226 
01227     return xp;
01228 }
01229 
01230 
01231 
01240 void  set_around(WSGraph vp, int cc)
01241 {
01242     int  i, px1, px2;
01243 
01244     for (i=0; i<vp.xs; i++){
01245         px1 = i;
01246         px2 = (vp.ys-1)*vp.xs + i;
01247         vp.gp[px1] = cc;
01248         vp.gp[px2] = cc;
01249     }
01250     for (i=1; i<vp.ys-1; i++){
01251         px1 = vp.xs*i;
01252         px2 = vp.xs*(i+1) - 1;
01253         vp.gp[px1] = cc;
01254         vp.gp[px2] = cc;
01255     }
01256 }
01257 
01258 
01259 
01271 WSGraph  zoom_WSGraph(WSGraph vp, int zm, int mode)
01272 {
01273     WSGraph  vx;
01274     int  i, j, k, l, m, n;
01275     sWord ws, wt;
01276 
01277     memset(&vx, 0, sizeof(WSGraph));
01278     if (zm<1) {
01279         vx.state = JBXL_GRAPH_IVDARG_ERROR;
01280         return vx;
01281     }
01282 
01283     vx = make_WSGraph(vp.xs*zm, vp.ys*zm, 1);
01284     if (vx.gp==NULL) {
01285         memset(&vx, 0, sizeof(WSGraph));
01286         vx.state = JBXL_GRAPH_MEMORY_ERROR;
01287         return vx;
01288     }
01289 
01290     if (mode==1){
01291         for(j=0; j<vp.ys; j++) {
01292             for(i=0; i<vp.xs; i++) {
01293                 m = i + j*vp.xs;
01294                 n = (i + j*vx.xs)*zm;
01295                 if(i==vp.xs-1) wt = 0;
01296                 else           wt = (vp.gp[m+1] - vp.gp[m])/zm;
01297                 if(j==vp.ys-1) ws = 0;
01298                 else           ws = (vp.gp[m+vp.xs] - vp.gp[m])/zm;
01299 
01300                 for(k=0; k<zm; k++) {
01301                     for(l=0; l<zm; l++) {
01302                         vx.gp[n+l+k*vx.xs] = ws*k + wt*l + vp.gp[m];
01303                     }
01304                 }
01305             }
01306         }
01307     }
01308     else {
01309         for(j=0; j<vp.ys; j++) {
01310             for(i=0; i<vp.xs; i++) {
01311                 m = i + j*vp.xs;
01312                 n = (i + j*vx.xs)*zm;
01313                 for(k=0; k<zm; k++) {
01314                     for(l=0; l<zm; l++) {
01315                         vx.gp[n+l+k*vx.xs] = vp.gp[m];
01316                     }
01317                 }
01318             }
01319         }
01320     }
01321     return vx;
01322 }
01323 
01324 
01325 
01338 WSGraph  grab_WSGraph(WSGraph vp, int x1, int y1, int x2, int y2)
01339 {
01340     int  i, j, xs, xe, ys, ye, xsize, ysize;
01341     WSGraph xp;
01342 
01343     xs = Min(x1, x2);
01344     xe = Max(x1, x2);
01345     xe = Min(xe, vp.xs-1);
01346     ys = Min(y1, y2);
01347     ye = Max(y1, y2);
01348     ye = Min(ye, vp.ys-1);
01349     xsize = xe - xs + 1;
01350     ysize = ye - ys + 1;
01351 
01352     xp = make_WSGraph(xsize, ysize, 1);
01353     if (xp.gp==NULL) {
01354         memset(&xp, 0, sizeof(WSGraph));
01355         xp.state = JBXL_GRAPH_MEMORY_ERROR;
01356         return xp;
01357     }
01358 
01359     for (j=0; j<ysize; j++) {
01360         for (i=0; i<xsize; i++) {
01361             Px(xp, i, j) = Px(vp, i+xs, j+ys);
01362         }
01363     }
01364 
01365     return xp;
01366 }
01367 
01368 
01369 
01380 void  copy_WSGraph(WSGraph src, WSGraph dst)
01381 {
01382     int  i, ssz, dsz, sz;
01383 
01384     if (src.zs<=0) src.zs = 1;
01385     if (dst.zs<=0) dst.zs = 1;
01386     ssz = src.xs*src.ys*src.zs;
01387     dsz = dst.xs*dst.ys*dst.zs;
01388     sz  = Min(ssz, dsz);
01389     
01390     for (i=0;  i<sz;  i++) dst.gp[i] = src.gp[i];
01391     for (i=sz; i<dsz; i++) dst.gp[i] = 0;
01392     return;
01393 }
01394 
01395 
01396